git-svn-id: svn://db.shs.com.ru/libs@626 a8b55f48-bf90-11e4-a774-851b48703e85
This commit is contained in:
296
qglengine/glrendererbase.cpp
Normal file
296
qglengine/glrendererbase.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
QGLView
|
||||
Copyright (C) 2019 Ivan Pelipenko peri4ko@yandex.ru
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "glrendererbase.h"
|
||||
#include "globject.h"
|
||||
#include "qglview.h"
|
||||
|
||||
|
||||
GLRendererBase::GLRendererBase(QGLView * view_): view(view_) {
|
||||
white_image = QImage(1, 1, QImage::Format_ARGB32);
|
||||
white_image.fill(0xFFFFFFFF);
|
||||
white_image_id = 0;
|
||||
violent_image = QImage(1, 1, QImage::Format_ARGB32);
|
||||
violent_image.fill(QColor(127, 127, 255));
|
||||
violent_image_id = 0;
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) {
|
||||
QVector3D lp = l.worldPos(), ld;// = (l.itransform_ * QVector4D(l.direction, 0.)).toVector3D().normalized();
|
||||
GLfloat pos[] = {0.f, 0.f, 0.f, 0.f};
|
||||
GLfloat dir[] = {0.f, 0.f, 0.f};
|
||||
GLfloat col[] = {0.f, 0.f, 0.f};
|
||||
pos[0] = l.light_type == Light::Directional ? -l.direction.x() : lp.x();
|
||||
pos[1] = l.light_type == Light::Directional ? -l.direction.y() : lp.y();
|
||||
pos[2] = l.light_type == Light::Directional ? -l.direction.z() : lp.z();
|
||||
pos[3] = l.light_type == Light::Directional ? 0. : 1.;
|
||||
dir[0] = ld.x();
|
||||
dir[1] = ld.y();
|
||||
dir[2] = ld.z();
|
||||
//col[0] = l.visible_ ? l.color().redF() * l.intensity : 0.f;
|
||||
//col[1] = l.visible_ ? l.color().greenF() * l.intensity : 0.f;
|
||||
//col[2] = l.visible_ ? l.color().blueF() * l.intensity : 0.f;
|
||||
glEnable(gl_index);
|
||||
//glLightfv(gl_index, GL_AMBIENT, ambient);
|
||||
glLightfv(gl_index, GL_DIFFUSE, col);
|
||||
glLightfv(gl_index, GL_SPECULAR, col);
|
||||
glLightfv(gl_index, GL_POSITION, pos);
|
||||
glLightf(gl_index, GL_CONSTANT_ATTENUATION, l.decay_const);
|
||||
glLightf(gl_index, GL_LINEAR_ATTENUATION, l.decay_linear);
|
||||
glLightf(gl_index, GL_QUADRATIC_ATTENUATION, l.decay_quadratic);
|
||||
if (l.light_type == Light::Cone) {
|
||||
glLightfv(gl_index, GL_SPOT_DIRECTION, dir);
|
||||
glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_end / 2.f);
|
||||
glLightf(gl_index, GL_SPOT_EXPONENT, (1.f - piClamp<float>((l.angle_end - l.angle_start) / (l.angle_end + 0.001f), 0., 1.f)) * 128.f);
|
||||
} else {
|
||||
glLightf(gl_index, GL_SPOT_CUTOFF, 180.);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupAmbientLight(const QColor & a, bool first_pass) {
|
||||
GLfloat ambient[] = {0.0f, 0.0f, 0.0f, 1.f};
|
||||
if (first_pass) {
|
||||
ambient[0] = view->ambientColor_.redF();
|
||||
ambient[1] = view->ambientColor_.greenF();
|
||||
ambient[2] = view->ambientColor_.blueF();
|
||||
}
|
||||
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::setupShadersLights(int lights_count) {
|
||||
/*foreach (QOpenGLShaderProgram * i, view->shaders_ppl) {
|
||||
i->bind();
|
||||
i->setUniformValue("lightsCount", lights_count);
|
||||
i->setUniformValue("acc_light", lights_count > 0);
|
||||
//i->setUniformValue("mat", mvm);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
#define BIND_TEXTURE(ch, map) if (rp.prev_tex[ch] != mat.map.bitmap_id) { \
|
||||
rp.prev_tex[ch] = mat.map.bitmap_id; \
|
||||
glActiveTexture(GL_TEXTURE0 + ch); glBindTexture(GL_TEXTURE_2D, mat.map.bitmap_id); \
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view->feature(QGLView::qglAnisotropicLevel).toInt());}
|
||||
|
||||
void GLRendererBase::setupTextures(ObjectBase & o, GLRendererBase::RenderingParameters & rp, bool first_object) {
|
||||
}
|
||||
|
||||
#undef BIND_TEXTURE
|
||||
|
||||
|
||||
void GLRendererBase::setupLights(int pass, int lights_per_pass) {
|
||||
/*int light_start, light_end, lmax;
|
||||
light_start = pass * lights_per_pass;
|
||||
light_end = qMin<int>((pass + 1) * lights_per_pass, view->lights_.size());
|
||||
setupAmbientLight(view->ambientColor_, pass == 0);
|
||||
if (!view->lights_.isEmpty()) {
|
||||
setupShadersLights(light_end - light_start);
|
||||
for (int i = light_start; i < light_end; ++i)
|
||||
setupLight(*view->lights_[i], i - light_start, GL_LIGHT0 + i - light_start);
|
||||
lmax = light_start + 8;
|
||||
for (int i = light_end; i < lmax; ++i)
|
||||
glDisable(GL_LIGHT0 + i - light_start);
|
||||
} else {
|
||||
setupShadersLights(0);
|
||||
for (int i = 0; i < 8; ++i)
|
||||
glDisable(GL_LIGHT0 + i);
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::applyFilteringParameters() {
|
||||
/*if (view->isFeatureEnabled(QGLView::qglLinearFiltering)) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
}*/
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, view->feature(QGLView::qglAnisotropicLevel).toInt());
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderObjects(int pass, int light_pass, void * shaders, bool textures, bool light, bool fog) {
|
||||
/*RenderingParameters rpl;
|
||||
rpl.pass = pass;
|
||||
rpl.light_pass = light_pass;
|
||||
rpl.shaders = shaders;
|
||||
rpl.textures = textures;
|
||||
rpl.light = rpl.prev_light = light;
|
||||
rpl.fog = rpl.prev_fog = fog;
|
||||
rpl.view_matrix = rp.view_matrix;
|
||||
rpl.prev_view_matrix = rp.prev_view_matrix;
|
||||
rpl.proj_matrix = rp.proj_matrix;
|
||||
rpl.prev_proj_matrix = rp.prev_proj_matrix;
|
||||
rpl.cam_offset_matrix = view->camera()->offsetMatrix();
|
||||
//qDebug() << "view:" << rp.view_matrix;
|
||||
for (int i = 0; i < 32; ++i) rpl.prev_tex[i] = 0;
|
||||
setupTextures(view->objects_, rpl, true);
|
||||
glSetCapEnabled(GL_TEXTURE_2D, rpl.textures);
|
||||
glSetCapEnabled(GL_BLEND, pass == ObjectBase::Transparent);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
glPushMatrix();
|
||||
renderSingleObject(view->objects_, rpl);
|
||||
glPopMatrix();*/
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderSingleObject(ObjectBase & o, RenderingParameters & rpl) {
|
||||
// if (!o.isInit())
|
||||
// o.init();
|
||||
// if (!o.isTexturesLoaded())
|
||||
// o.loadTextures();
|
||||
// if (!o.visible_) return;
|
||||
// if (rpl.pass == o.pass_) {
|
||||
// //Material & mat(o.material_);
|
||||
// QMatrix4x4 curview = rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_, prevview = rpl.prev_view_matrix * rpl.cam_offset_matrix * o.itransform_;
|
||||
// //setupTextures(o, rpl, false);
|
||||
// //mat.apply((QOpenGLShaderProgram*)rpl.shaders);
|
||||
// glSetPolygonMode(o.render_mode != ObjectBase::View ? o.render_mode : (view->rmode != ObjectBase::View ? view->rmode : GL_FILL));
|
||||
// glLineWidth(o.line_width > 0.f ? o.line_width : view->lineWidth_);
|
||||
// glPointSize(o.line_width > 0.f ? o.line_width : view->lineWidth_);
|
||||
// o.update();
|
||||
// /*if (o.pass_ == GLObjectBase::Transparent) {
|
||||
// glActiveTexture(GL_TEXTURE0 + 3);
|
||||
// if (mat.reflectivity > 0.f) {
|
||||
// glEnable(GL_TEXTURE_CUBE_MAP);
|
||||
// //if (!mat.map_reflection.isEmpty()) mat.map_reflection.bind();
|
||||
// //else glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
// } else glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
// if (rpl.light_pass > 0) glDisable(GL_TEXTURE_CUBE_MAP);
|
||||
// GLfloat gm[16], bc[4] = {mat.reflectivity, mat.reflectivity, mat.reflectivity, mat.reflectivity};
|
||||
// glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
|
||||
// glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE);
|
||||
// glTexEnvi(GL_TEXTURE_ENV, GL_SRC2_RGB, GL_CONSTANT);
|
||||
// glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR);
|
||||
// glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, bc);
|
||||
// glGetFloatv(GL_MODELVIEW_MATRIX, gm);
|
||||
// glMatrixMode(GL_TEXTURE);
|
||||
// ///glLoadTransposeMatrixf(gm);
|
||||
// glScalef(-1., -1., -1.);
|
||||
// glMatrixMode(GL_MODELVIEW);
|
||||
// glActiveTexture(GL_TEXTURE0);
|
||||
// }*/
|
||||
// if (rpl.shaders) {
|
||||
// //qDebug() << o.name() << curview << curview->determinant();
|
||||
// //setUniformMatrices((QOpenGLShaderProgram*)rpl.shaders, rpl.proj_matrix, curview, rpl.prev_proj_matrix, prevview);
|
||||
// } else {
|
||||
// glMatrixMode(GL_MODELVIEW);
|
||||
// //setGLMatrix(curview);
|
||||
// }
|
||||
// o.draw((QOpenGLShaderProgram*)rpl.shaders);
|
||||
// }
|
||||
// foreach (ObjectBase * i, o.children_)
|
||||
// renderSingleObject(*i, rpl);
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderShadow(Light * l, QOpenGLShaderProgram * prog, QMatrix4x4 mat) {
|
||||
Camera cam;
|
||||
QVector3D wp = l->worldPos();
|
||||
cam.setPos(wp);
|
||||
cam.setAim(wp + (l->worldTransform() * QVector4D(l->direction)).toVector3D());
|
||||
cam.setDepthStart(view->camera()->depthStart());
|
||||
cam.setDepthEnd(view->camera()->depthEnd());
|
||||
cam.setFOV(l->angle_end);
|
||||
cam.apply(1.);
|
||||
/*cam.rotateXY(l->angle_end);
|
||||
QVector3D rdir = l->direction * cos(l->angle_end / 2. * deg2rad);
|
||||
l->dir0 = cam.direction() - rdir;
|
||||
cam.rotateXY(-l->angle_end);
|
||||
cam.rotateZ(l->angle_end);
|
||||
l->dir1 = cam.direction() - rdir;*/
|
||||
//qDebug() << rdir << l->dir0 << l->dir1;
|
||||
RenderingParameters rpl;
|
||||
rpl.pass = ObjectBase::Solid;
|
||||
rpl.shaders = prog;
|
||||
rpl.textures = rpl.light = rpl.fog = false;
|
||||
//rpl.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX);
|
||||
//rpl.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX);
|
||||
rpl.cam_offset_matrix = cam.offsetMatrix();
|
||||
QMatrix4x4 mbias;
|
||||
mbias.scale(0.5, 0.5, 0.5);
|
||||
mbias.translate(1., 1., 1.);
|
||||
l->shadow_matrix = mbias*rpl.proj_matrix*rpl.view_matrix*rpl.cam_offset_matrix*mat;//;// * mbias;
|
||||
//qDebug() << mbias;
|
||||
//glPushMatrix();
|
||||
//renderSingleShadow(view->objects_, rpl);
|
||||
//glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::renderSingleShadow(ObjectBase & o, RenderingParameters & rpl) {
|
||||
// if (!o.isInit())
|
||||
// o.init();
|
||||
// if (!o.visible_) return;
|
||||
// if (rpl.shaders) {
|
||||
// //qDebug() << o.name() << curview << curview->determinant();
|
||||
// //setUniformMatrices((QOpenGLShaderProgram*)rpl.shaders, rpl.proj_matrix, rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_);
|
||||
// } else {
|
||||
// glMatrixMode(GL_MODELVIEW);
|
||||
// //setGLMatrix(rpl.view_matrix * rpl.cam_offset_matrix * o.itransform_);
|
||||
// }
|
||||
// glPolygonMode(GL_FRONT_AND_BACK, o.render_mode != ObjectBase::View ? o.render_mode : (view->rmode != ObjectBase::View ? view->rmode : GL_FILL));
|
||||
// glLineWidth(o.line_width > 0.f ? o.line_width : view->lineWidth_);
|
||||
// glPointSize(o.line_width > 0.f ? o.line_width : view->lineWidth_);
|
||||
// o.draw((QOpenGLShaderProgram*)rpl.shaders, true);
|
||||
// foreach (ObjectBase * i, o.children_)
|
||||
// renderSingleShadow(*i, rpl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
GLRendererBase::RenderingParameters::RenderingParameters() {
|
||||
shaders = nullptr;
|
||||
cur_shader = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::RenderingParameters::prepare() {
|
||||
//proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX);
|
||||
//view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX);
|
||||
viewproj_matrix = proj_matrix * view_matrix;
|
||||
normal_matrix = view_matrix.normalMatrix();
|
||||
proj_matrix_i = proj_matrix.inverted();
|
||||
view_matrix_i = view_matrix.inverted();
|
||||
viewproj_matrix_i = viewproj_matrix.inverted();
|
||||
}
|
||||
|
||||
|
||||
void GLRendererBase::RenderingParameters::setUniform(QOpenGLShaderProgram * prog) {
|
||||
if (!prog) return;
|
||||
prog->setUniformValue("qgl_ModelViewMatrix", view_matrix);
|
||||
prog->setUniformValue("qgl_ProjectionMatrix", proj_matrix);
|
||||
prog->setUniformValue("qgl_ModelViewProjectionMatrix", viewproj_matrix);
|
||||
prog->setUniformValue("qgl_NormalMatrix", normal_matrix);
|
||||
prog->setUniformValue("qgl_ModelViewMatrixInverse", view_matrix_i);
|
||||
prog->setUniformValue("qgl_ProjectionMatrixInverse", proj_matrix_i);
|
||||
prog->setUniformValue("qgl_ModelViewProjectionMatrixInverse", viewproj_matrix_i);
|
||||
prog->setUniformValue("qgl_ModelViewMatrixTranspose", view_matrix.transposed());
|
||||
prog->setUniformValue("qgl_ProjectionMatrixTranspose", proj_matrix.transposed());
|
||||
prog->setUniformValue("qgl_ModelViewProjectionMatrixTranspose", viewproj_matrix.transposed());
|
||||
prog->setUniformValue("qgl_ModelViewMatrixInverseTranspose", view_matrix_i.transposed());
|
||||
prog->setUniformValue("qgl_ProjectionMatrixInverseTranspose", proj_matrix_i.transposed());
|
||||
prog->setUniformValue("qgl_ModelViewProjectionMatrixInverseTranspose", viewproj_matrix_i.transposed());
|
||||
}
|
||||
Reference in New Issue
Block a user