code format
This commit is contained in:
@@ -1,46 +1,46 @@
|
||||
/*
|
||||
QGL RendererBase
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
QGL RendererBase
|
||||
Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <QOpenGLExtraFunctions>
|
||||
#include "renderer_base.h"
|
||||
#include "renderer.h"
|
||||
#include "qglview.h"
|
||||
|
||||
#include "glmesh.h"
|
||||
#include "gltexture_manager.h"
|
||||
#include "glshaders_headers.h"
|
||||
#include "gltexture_manager.h"
|
||||
#include "qglview.h"
|
||||
#include "renderer.h"
|
||||
|
||||
#include <QOpenGLExtraFunctions>
|
||||
|
||||
using namespace QGLEngineShaders;
|
||||
|
||||
|
||||
RendererBase::RendererBase(QGLView * view_):
|
||||
view(view_),
|
||||
buffer_materials (GL_UNIFORM_BUFFER, GL_STREAM_DRAW),
|
||||
buffer_lights (GL_UNIFORM_BUFFER, GL_STREAM_DRAW),
|
||||
buffer_lights_pos(GL_UNIFORM_BUFFER, GL_STREAM_DRAW),
|
||||
textures_empty(false),
|
||||
textures_maps(true)
|
||||
{
|
||||
RendererBase::RendererBase(QGLView * view_)
|
||||
: view(view_)
|
||||
, buffer_materials(GL_UNIFORM_BUFFER, GL_STREAM_DRAW)
|
||||
, buffer_lights(GL_UNIFORM_BUFFER, GL_STREAM_DRAW)
|
||||
, buffer_lights_pos(GL_UNIFORM_BUFFER, GL_STREAM_DRAW)
|
||||
, textures_empty(false)
|
||||
, textures_maps(true) {
|
||||
textures_manager = new TextureManager(view);
|
||||
maps_size = QSize(512, 512);
|
||||
maps_hash = 0;
|
||||
maps_size = QSize(512, 512);
|
||||
maps_hash = 0;
|
||||
tex_coeff[0] = tex_coeff[1] = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -68,23 +68,23 @@ void RendererBase::initUniformBuffer(QOpenGLShaderProgram * prog, Buffer * buffe
|
||||
if (!prog->isLinked()) return;
|
||||
QOpenGLExtraFunctions * f = view;
|
||||
buffer->init(f);
|
||||
//glClearError();
|
||||
// glClearError();
|
||||
GLint ubo_ind = f->glGetUniformBlockIndex(prog->programId(), blockName);
|
||||
f->glUniformBlockBinding(prog->programId(), ubo_ind, bind_point);
|
||||
f->glBindBufferBase(GL_UNIFORM_BUFFER, bind_point, buffer->ID());
|
||||
//qDebug() << "initUBO" << QString::number(f->glGetError(), 16);
|
||||
// qDebug() << "initUBO" << QString::number(f->glGetError(), 16);
|
||||
}
|
||||
|
||||
|
||||
void RendererBase::setUniformHalo(QOpenGLShaderProgram * prog, const char * type, QColor color, float fill) {
|
||||
prog->setUniformValue((QString(type) + "_color").toLatin1().constData(), color);
|
||||
prog->setUniformValue((QString(type) + "_fill" ).toLatin1().constData(), fill);
|
||||
prog->setUniformValue((QString(type) + "_fill").toLatin1().constData(), fill);
|
||||
}
|
||||
|
||||
|
||||
void RendererBase::setUniformMaps(QOpenGLShaderProgram * prog) {
|
||||
prog->setUniformValue("qgl_texture_array[0]", (int)tarEmpty);
|
||||
prog->setUniformValue("qgl_texture_array[1]", (int)tarMaps );
|
||||
prog->setUniformValue("qgl_texture_array[1]", (int)tarMaps);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ void RendererBase::setUniformCamera(QOpenGLShaderProgram * prog, Camera * cam, b
|
||||
prog->setUniformValue("z_near", cam->depthStart());
|
||||
}
|
||||
prog->setUniformValue("dt", QVector2D(1. / w, 1. / h));
|
||||
prog->setUniformValue("qgl_ViewMatrix" , mat_view);
|
||||
prog->setUniformValue("qgl_ViewMatrix", mat_view);
|
||||
prog->setUniformValue("qgl_ViewProjMatrix", mat_proj * mat_view);
|
||||
}
|
||||
|
||||
@@ -118,9 +118,9 @@ void RendererBase::setUniformViewCorners(QOpenGLShaderProgram * prog, Camera * c
|
||||
QMatrix4x4 mviewi = cam->viewMatrix().inverted();
|
||||
QVector4D corner_dirs[4], world_dirs[4];
|
||||
corner_dirs[0] = (mproji * QVector4D(-1, -1, 0, 1));
|
||||
corner_dirs[1] = (mproji * QVector4D(-1, 1, 0, 1));
|
||||
corner_dirs[2] = (mproji * QVector4D( 1, 1, 0, 1));
|
||||
corner_dirs[3] = (mproji * QVector4D( 1, -1, 0, 1));
|
||||
corner_dirs[1] = (mproji * QVector4D(-1, 1, 0, 1));
|
||||
corner_dirs[2] = (mproji * QVector4D(1, 1, 0, 1));
|
||||
corner_dirs[3] = (mproji * QVector4D(1, -1, 0, 1));
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
world_dirs[i] = QVector4D(mviewi.mapVector(corner_dirs[i].toVector3D()));
|
||||
prog->setUniformValue(QString("view_corners[%1]").arg(i).toLatin1().constData(), corner_dirs[i]);
|
||||
@@ -145,19 +145,19 @@ void RendererBase::fillSelectionsBuffer(QVector<uchar> & buffer, bool yes, int s
|
||||
|
||||
|
||||
void RendererBase::reloadMaterials(Scene & scene) {
|
||||
//qDebug() << "reloadMaterias";
|
||||
QList<Map*> maps[2];
|
||||
// qDebug() << "reloadMaterias";
|
||||
QList<Map *> maps[2];
|
||||
QMap<QString, int> tex_layers[2];
|
||||
foreach (Material * m, scene.materials) {
|
||||
if (m->map_diffuse .hasBitmap()) maps[0] << &(m->map_diffuse );
|
||||
if (m->map_normal .hasBitmap()) maps[1] << &(m->map_normal );
|
||||
foreach(Material * m, scene.materials) {
|
||||
if (m->map_diffuse.hasBitmap()) maps[0] << &(m->map_diffuse);
|
||||
if (m->map_normal.hasBitmap()) maps[1] << &(m->map_normal);
|
||||
if (m->map_metalness.hasBitmap()) maps[0] << &(m->map_metalness);
|
||||
if (m->map_roughness.hasBitmap()) maps[0] << &(m->map_roughness);
|
||||
if (m->map_emission .hasBitmap()) maps[0] << &(m->map_emission );
|
||||
if (m->map_relief .hasBitmap()) maps[0] << &(m->map_relief );
|
||||
if (m->map_emission.hasBitmap()) maps[0] << &(m->map_emission);
|
||||
if (m->map_relief.hasBitmap()) maps[0] << &(m->map_relief);
|
||||
}
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
foreach (Map * m, maps[i])
|
||||
foreach(Map * m, maps[i])
|
||||
tex_layers[i][m->bitmap_path] = 0;
|
||||
}
|
||||
int layers_count = tex_layers[0].size() + tex_layers[1].size(), cl = -1;
|
||||
@@ -174,52 +174,51 @@ void RendererBase::reloadMaterials(Scene & scene) {
|
||||
textures_maps.load(view, im, ++cl);
|
||||
it.value() = cl;
|
||||
}
|
||||
foreach (Map * m, maps[i]) {
|
||||
foreach(Map * m, maps[i]) {
|
||||
m->_layer = tex_layers[i].value(m->bitmap_path);
|
||||
//qDebug() << "assign" << m->bitmap_path << "layer" << m->_layer;
|
||||
// qDebug() << "assign" << m->bitmap_path << "layer" << m->_layer;
|
||||
}
|
||||
}
|
||||
textures_maps.mipmaps(view);
|
||||
// qDebug() << "load" << (cl+1) << "bitmaps";
|
||||
// qDebug() << "load" << (cl+1) << "bitmaps";
|
||||
}
|
||||
|
||||
QGLMaterial glm;
|
||||
cur_materials_.clear();
|
||||
cur_materials_ << glm;
|
||||
foreach (Material * m, scene.materials) {
|
||||
foreach(Material * m, scene.materials) {
|
||||
if (cur_materials_.size() >= max_materials) {
|
||||
qDebug() << "[QGLEngine] Warning: Too many materials! Maximum" << max_materials;
|
||||
break;
|
||||
}
|
||||
m->_index = cur_materials_.size();
|
||||
m->_changed = false;
|
||||
glm.color_diffuse = QColor2QVector(m->color_diffuse );
|
||||
m->_index = cur_materials_.size();
|
||||
m->_changed = false;
|
||||
glm.color_diffuse = QColor2QVector(m->color_diffuse);
|
||||
glm.color_emission = QColor2QVector(m->color_emission);
|
||||
glm.transparency = m->transparency;
|
||||
glm.reflectivity = m->reflectivity;
|
||||
glm.iof = m->iof ;
|
||||
glm.dispersion = m->dispersion ;
|
||||
m->map_diffuse .copyToQGLMap(glm.map[mtDiffuse ]);
|
||||
m->map_normal .copyToQGLMap(glm.map[mtNormal ]);
|
||||
m->map_metalness.copyToQGLMap(glm.map[mtMetalness ]);
|
||||
glm.transparency = m->transparency;
|
||||
glm.reflectivity = m->reflectivity;
|
||||
glm.iof = m->iof;
|
||||
glm.dispersion = m->dispersion;
|
||||
m->map_diffuse.copyToQGLMap(glm.map[mtDiffuse]);
|
||||
m->map_normal.copyToQGLMap(glm.map[mtNormal]);
|
||||
m->map_metalness.copyToQGLMap(glm.map[mtMetalness]);
|
||||
m->map_roughness.copyToQGLMap(glm.map[mtRoughness]);
|
||||
m->map_emission .copyToQGLMap(glm.map[mtEmission ]);
|
||||
m->map_relief .copyToQGLMap(glm.map[mtRelief ]);
|
||||
m->map_emission.copyToQGLMap(glm.map[mtEmission]);
|
||||
m->map_relief.copyToQGLMap(glm.map[mtRelief]);
|
||||
cur_materials_ << glm;
|
||||
}
|
||||
//qDebug() << "load" << cur_materials_.size() << "materials";
|
||||
// qDebug() << "load" << cur_materials_.size() << "materials";
|
||||
buffer_materials.bind(view);
|
||||
buffer_materials.resize(view, cur_materials_.size() * sizeof(QGLMaterial));
|
||||
buffer_materials.load(view, cur_materials_.constData(), cur_materials_.size() * sizeof(QGLMaterial));
|
||||
scene.need_reload_materials = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RendererBase::reloadLightsParameters(const QMap<int, QList<Light*>> & lights) {
|
||||
void RendererBase::reloadLightsParameters(const QMap<int, QList<Light *>> & lights) {
|
||||
lights_start.clear();
|
||||
lights_start[Light::Omni] = 0;
|
||||
QMapIterator<int, QList<Light*>> it(lights);
|
||||
QMapIterator<int, QList<Light *>> it(lights);
|
||||
current_lights.clear();
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
@@ -227,19 +226,18 @@ void RendererBase::reloadLightsParameters(const QMap<int, QList<Light*>> & light
|
||||
current_lights.append(it.value());
|
||||
}
|
||||
cur_lights_params_.resize(qMin(current_lights.size(), max_lights));
|
||||
//qDebug() << "reloadLightsParameters" << cur_lights_params_.size();
|
||||
// qDebug() << "reloadLightsParameters" << cur_lights_params_.size();
|
||||
for (int i = 0; i < cur_lights_params_.size(); ++i) {
|
||||
QGLLightParameter & so(cur_lights_params_[i]);
|
||||
Light * l = current_lights[i];
|
||||
Light * l = current_lights[i];
|
||||
double ang_start = l->angle_start / 2.f, ang_end = l->angle_end / 2.f;
|
||||
if (l->light_type == Light::Omni)
|
||||
ang_start = ang_end = 180.;
|
||||
//qDebug() << "light" << light->name() << ulightn << pos;
|
||||
so.color = QColor2QVector(l->color_);
|
||||
so.angles[0] = ang_start;
|
||||
so.angles[1] = cos(ang_start * deg2rad);
|
||||
so.angles[2] = ang_end;
|
||||
so.angles[3] = cos(ang_end * deg2rad);
|
||||
if (l->light_type == Light::Omni) ang_start = ang_end = 180.;
|
||||
// qDebug() << "light" << light->name() << ulightn << pos;
|
||||
so.color = QColor2QVector(l->color_);
|
||||
so.angles[0] = ang_start;
|
||||
so.angles[1] = cos(ang_start * deg2rad);
|
||||
so.angles[2] = ang_end;
|
||||
so.angles[3] = cos(ang_end * deg2rad);
|
||||
so.decay_intensity[0] = l->decay_const;
|
||||
so.decay_intensity[1] = l->decay_linear;
|
||||
so.decay_intensity[2] = l->decay_quadratic;
|
||||
@@ -256,12 +254,12 @@ void RendererBase::reloadLightsPositions(Camera * cam) {
|
||||
QMatrix4x4 mat = cam->viewMatrix() * cam->offsetMatrix();
|
||||
for (int i = 0; i < cur_lights_pos_.size(); ++i) {
|
||||
QGLLightPosition & so(cur_lights_pos_[i]);
|
||||
Light * l = current_lights[i];
|
||||
Light * l = current_lights[i];
|
||||
QMatrix4x4 m = mat * l->worldTransform();
|
||||
QVector4D pos(0, 0, 0, 1.), dir(QVector3D(0,0,-1), 1);
|
||||
pos = m * pos;
|
||||
dir = (m * QVector4D(QVector3D(0,0,-1),0)).normalized();
|
||||
so.position = pos;
|
||||
QVector4D pos(0, 0, 0, 1.), dir(QVector3D(0, 0, -1), 1);
|
||||
pos = m * pos;
|
||||
dir = (m * QVector4D(QVector3D(0, 0, -1), 0)).normalized();
|
||||
so.position = pos;
|
||||
so.direction = dir;
|
||||
}
|
||||
buffer_lights_pos.bind(view);
|
||||
@@ -293,8 +291,7 @@ void RendererBase::initQuad(Mesh * mesh, QMatrix4x4 mat) {
|
||||
|
||||
void RendererBase::renderQuad(QOpenGLShaderProgram * prog, Mesh * mesh, Camera * cam, bool uniforms) {
|
||||
glDisableDepth();
|
||||
if (uniforms)
|
||||
setUniformCamera(prog, cam, false);
|
||||
if (uniforms) setUniformCamera(prog, cam, false);
|
||||
mesh->draw(view, 1);
|
||||
}
|
||||
|
||||
@@ -312,20 +309,20 @@ float RadicalInverse_VdC(uint bits) {
|
||||
|
||||
|
||||
QVector2D Hammersley(uint i, uint N) {
|
||||
return QVector2D(float(i)/float(N), RadicalInverse_VdC(i));
|
||||
return QVector2D(float(i) / float(N), RadicalInverse_VdC(i));
|
||||
}
|
||||
|
||||
|
||||
QVector3D ImportanceSampleGGX(QVector2D Xi, QVector3D N, float roughness) {
|
||||
float a = roughness*roughness;
|
||||
float phi = 2.0 * M_PI * Xi[0];
|
||||
float cosTheta = sqrt((1.0 - Xi[1]) / (1.0 + (a*a - 1.0) * Xi[1]));
|
||||
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
|
||||
float a = roughness * roughness;
|
||||
float phi = 2.0 * M_PI * Xi[0];
|
||||
float cosTheta = sqrt((1.0 - Xi[1]) / (1.0 + (a * a - 1.0) * Xi[1]));
|
||||
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
|
||||
// преобразование из сферических в декартовы координаты
|
||||
QVector3D H;
|
||||
H[0] = cos(phi) * sinTheta;
|
||||
H[1] = sin(phi) * sinTheta;
|
||||
H[2] = cosTheta;
|
||||
H[0] = cos(phi) * sinTheta;
|
||||
H[1] = sin(phi) * sinTheta;
|
||||
H[2] = cosTheta;
|
||||
// преобразование из касательного пространства в мировые координаты
|
||||
QVector3D up = qAbs(N[2]) < 0.999 ? QVector3D(0.0, 0.0, 1.0) : QVector3D(1.0, 0.0, 0.0);
|
||||
QVector3D tangent = QVector3D::crossProduct(up, N).normalized();
|
||||
@@ -336,7 +333,7 @@ QVector3D ImportanceSampleGGX(QVector2D Xi, QVector3D N, float roughness) {
|
||||
|
||||
|
||||
float GeometrySchlickGGX(float NdotV, float roughness) {
|
||||
float k = (roughness * roughness) / 2.0;
|
||||
float k = (roughness * roughness) / 2.0;
|
||||
float nom = NdotV;
|
||||
float denom = NdotV * (1.0 - k) + k;
|
||||
return nom / denom;
|
||||
@@ -346,32 +343,32 @@ float GeometrySchlickGGX(float NdotV, float roughness) {
|
||||
float GeometrySmith(QVector3D N, QVector3D V, QVector3D L, float roughness) {
|
||||
float NdotV = piMax(QVector3D::dotProduct(N, V), 0.f);
|
||||
float NdotL = piMax(QVector3D::dotProduct(N, L), 0.f);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
|
||||
QVector2D IntegrateBRDF(float NdotV, float roughness) {
|
||||
QVector3D V;
|
||||
V[0] = sqrt(1.f - NdotV*NdotV);
|
||||
V[1] = 0.f;
|
||||
V[2] = NdotV;
|
||||
float A = 0.f;
|
||||
float B = 0.f;
|
||||
QVector3D N = QVector3D(0.f, 0.f, 1.f);
|
||||
V[0] = sqrt(1.f - NdotV * NdotV);
|
||||
V[1] = 0.f;
|
||||
V[2] = NdotV;
|
||||
float A = 0.f;
|
||||
float B = 0.f;
|
||||
QVector3D N = QVector3D(0.f, 0.f, 1.f);
|
||||
const uint SAMPLE_COUNT = 256u;
|
||||
for(uint i = 0u; i < SAMPLE_COUNT; ++i) {
|
||||
for (uint i = 0u; i < SAMPLE_COUNT; ++i) {
|
||||
QVector2D Xi = Hammersley(i, SAMPLE_COUNT);
|
||||
QVector3D H = ImportanceSampleGGX(Xi, N, roughness);
|
||||
QVector3D L = (2.f * QVector3D::dotProduct(V, H) * H - V).normalized();
|
||||
float NdotL = piMax(L[2], 0.f);
|
||||
float NdotH = piMax(H[2], 0.f);
|
||||
float VdotH = piMax(QVector3D::dotProduct(V, H), 0.f);
|
||||
if(NdotL > 0.f) {
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
float NdotL = piMax(L[2], 0.f);
|
||||
float NdotH = piMax(H[2], 0.f);
|
||||
float VdotH = piMax(QVector3D::dotProduct(V, H), 0.f);
|
||||
if (NdotL > 0.f) {
|
||||
float G = GeometrySmith(N, V, L, roughness);
|
||||
float G_Vis = (G * VdotH) / (NdotH * NdotV);
|
||||
float Fc = pow(1.f - VdotH, 5.f);
|
||||
float Fc = pow(1.f - VdotH, 5.f);
|
||||
A += (1.f - Fc) * G_Vis;
|
||||
B += Fc * G_Vis;
|
||||
}
|
||||
@@ -384,12 +381,12 @@ QVector2D IntegrateBRDF(float NdotV, float roughness) {
|
||||
|
||||
void RendererBase::initCoeffTextures() {
|
||||
QImage im = QImage(":/coeffs_brdf.png").mirrored();
|
||||
int size = im.width();
|
||||
QVector<QVector2D> data(size*size);
|
||||
int size = im.width();
|
||||
QVector<QVector2D> data(size * size);
|
||||
int ind = -1;
|
||||
for (int x = 0; x < size; ++x) {
|
||||
for (int y = 0; y < size; ++y) {
|
||||
QColor p = im.pixelColor(x, y);
|
||||
QColor p = im.pixelColor(x, y);
|
||||
data[++ind] = QVector2D(p.redF(), p.greenF());
|
||||
}
|
||||
}
|
||||
@@ -408,8 +405,17 @@ void RendererBase::createCoeffTexture(GLuint & id, const void * data, int size,
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
GLenum iformat = GL_R16F, format = GL_RED;
|
||||
if (channels == 2) {iformat = GL_RG16F; format = GL_RG;}
|
||||
if (channels == 3) {iformat = GL_RGB16F; format = GL_RGB;}
|
||||
if (channels == 4) {iformat = GL_RGBA16F; format = GL_RGBA;}
|
||||
if (channels == 2) {
|
||||
iformat = GL_RG16F;
|
||||
format = GL_RG;
|
||||
}
|
||||
if (channels == 3) {
|
||||
iformat = GL_RGB16F;
|
||||
format = GL_RGB;
|
||||
}
|
||||
if (channels == 4) {
|
||||
iformat = GL_RGBA16F;
|
||||
format = GL_RGBA;
|
||||
}
|
||||
f->glTexImage2D(GL_TEXTURE_2D, 0, iformat, size, size, 0, format, GL_FLOAT, data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user