diff --git a/qglview/globject.cpp b/qglview/globject.cpp index f5fd19f..a5f8286 100644 --- a/qglview/globject.cpp +++ b/qglview/globject.cpp @@ -210,7 +210,7 @@ void GLObjectBase::render(int * id, QMap * ids, int sh_id_ -Light::Light(): GLObjectBase(), shadow_map(true, 1, GL_R16F) { +Light::Light(): GLObjectBase(), shadow_map(1, true, GL_R16F) { type_ = GLObjectBase::Light; light_type = Omni; intensity = 1.; @@ -221,7 +221,7 @@ Light::Light(): GLObjectBase(), shadow_map(true, 1, GL_R16F) { } -Light::Light(const QVector3D & p, const QColor & c, GLdouble i): GLObjectBase(), shadow_map(true, 1, GL_R16F) { +Light::Light(const QVector3D & p, const QColor & c, GLdouble i): GLObjectBase(), shadow_map(1, true, GL_R16F) { type_ = GLObjectBase::Light; light_type = Omni; pos_ = p; diff --git a/qglview/globject.h b/qglview/globject.h index cbc60aa..810bc0d 100644 --- a/qglview/globject.h +++ b/qglview/globject.h @@ -230,11 +230,11 @@ public: GLdouble decay_start; GLdouble decay_end; Type light_type; - -protected: GLFramebuffer shadow_map; QMatrix4x4 shadow_matrix; +protected: + }; template diff --git a/qglview/glrendererbase.cpp b/qglview/glrendererbase.cpp index 71d5543..0571481 100644 --- a/qglview/glrendererbase.cpp +++ b/qglview/glrendererbase.cpp @@ -229,6 +229,38 @@ void GLRendererBase::renderSingleObject(GLObjectBase & o, RenderingParameters & } +void GLRendererBase::renderShadow(Light * l) { + Camera cam; + QVector3D wp = l->worldPos(); + cam.setPos(wp); + cam.setAim(wp + (l->worldTransform() * QVector4D(l->direction, 0).toVector3D())); + cam.apply(1.); + RenderingParameters rpl; + rpl.pass = GLObjectBase::Solid; + rpl.shaders = 0; + rpl.textures = rpl.light = rpl.fog = false; + rpl.view_matrix = getGLMatrix(GL_MODELVIEW_MATRIX); + rpl.proj_matrix = getGLMatrix(GL_PROJECTION_MATRIX); + //glPushMatrix(); + renderSingleShadow(view.objects_, rpl); + //glPopMatrix(); +} + + +void GLRendererBase::renderSingleShadow(GLObjectBase & o, RenderingParameters & rpl) { + if (!o.isInit()) + o.init(); + if (!o.visible_) return; + setGLMatrix(rpl.view_matrix * o.itransform_); + glPolygonMode(GL_FRONT_AND_BACK, o.render_mode != GLObjectBase::View ? o.render_mode : (view.rmode != GLObjectBase::View ? view.rmode : GL_FILL)); + glLineWidth(o.line_width > 0. ? o.line_width : view.lineWidth_); + glPointSize(o.line_width > 0. ? o.line_width : view.lineWidth_); + o.draw(0, true); + foreach (GLObjectBase * i, o.children_) + renderSingleShadow(*i, rpl); +} + + void GLRendererBase::RenderingParameters::prepare() { diff --git a/qglview/glrendererbase.h b/qglview/glrendererbase.h index 3109783..f740164 100644 --- a/qglview/glrendererbase.h +++ b/qglview/glrendererbase.h @@ -64,6 +64,8 @@ protected: inline void applyFilteringParameters(); void renderObjects(int pass, int light_pass, void * shaders = 0, bool textures = true, bool light = true, bool fog = true); void renderSingleObject(GLObjectBase & o, RenderingParameters & rpl); + void renderShadow(Light * l); + void renderSingleShadow(GLObjectBase & o, RenderingParameters & rpl); RenderingParameters rp; QGLView & view; diff --git a/qglview/glshaders.cpp b/qglview/glshaders.cpp index a9d94cc..7caf54b 100644 --- a/qglview/glshaders.cpp +++ b/qglview/glshaders.cpp @@ -66,6 +66,7 @@ const char qgl_structs[] = " float linearAttenuation;\n" " float quadraticAttenuation;\n" " sampler2DShadow shadow;\n" + " mat4 shadowMatrix;\n" "};\n" "struct QGLMap {\n" " float offset;\n" @@ -194,9 +195,9 @@ void setUniformMaterial(QGLShaderProgram * prog, const Material & mat) { } -void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat, const QVector4D & dp) { +void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat, int shadow_start) { for (int i = 0; i < lights.size(); ++i) - setUniformLight(prog, lights[i], QString("qgl_Light[%1]").arg(i), mat, dp); + setUniformLight(prog, lights[i], QString("qgl_Light[%1]").arg(i), mat, shadow_start + i); } /* " vec3 position;\n" @@ -208,8 +209,10 @@ void setUniformLights(QGLShaderProgram * prog, const QVector & lights, c " float constantAttenuation;\n" " float linearAttenuation;\n" " float quadraticAttenuation;\n" +" sampler2DShadow shadow;\n" +" mat4 shadowMatrix;\n" */ -void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat, const QVector4D & dp) { +void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat, int shadow) { QMatrix4x4 m = mat * light->worldTransform(); QVector4D pos(0, 0, 0, 1.), dir(light->direction); pos = m * pos; @@ -229,4 +232,6 @@ void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, co prog->setUniformValue((ulightn + ".constantAttenuation").toLatin1().constData(), GLfloat(light->decay_const)); prog->setUniformValue((ulightn + ".linearAttenuation").toLatin1().constData(), GLfloat(light->decay_linear)); prog->setUniformValue((ulightn + ".quadraticAttenuation").toLatin1().constData(), GLfloat(light->decay_quadratic)); + prog->setUniformValue((ulightn + ".shadow").toLatin1().constData(), shadow); + prog->setUniformValue((ulightn + ".shadowMatrix").toLatin1().constData(), light->shadow_matrix); } diff --git a/qglview/glshaders.h b/qglview/glshaders.h index 5962c5b..979f961 100644 --- a/qglview/glshaders.h +++ b/qglview/glshaders.h @@ -30,7 +30,7 @@ bool loadShaders(QGLShaderProgram * prog, const QString & name, const QString & void setUniformMatrices(QGLShaderProgram * prog, QMatrix4x4 proj, QMatrix4x4 view, QMatrix4x4 prevproj = QMatrix4x4(), QMatrix4x4 prevview = QMatrix4x4()); void setUniformMap(QGLShaderProgram * prog, const Map & map, int channel, int def_channel); void setUniformMaterial(QGLShaderProgram * prog, const Material & mat); -void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat, const QVector4D & dp); -void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat = QMatrix4x4(), const QVector4D & dp = QVector4D()); +void setUniformLights(QGLShaderProgram * prog, const QVector & lights, const QMatrix4x4 & mat, int shadow_start); +void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat = QMatrix4x4(), int shadow = 0); #endif // GLSHADERS_H diff --git a/qglview/glvbo.cpp b/qglview/glvbo.cpp index 051c23e..4e7ee68 100644 --- a/qglview/glvbo.cpp +++ b/qglview/glvbo.cpp @@ -120,24 +120,25 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { //qDebug() << "draw" << vert_count; void * offset = (void*)(vert_count * 3 * sizeof(GLfloat)); //glBindVertexArray(va_); - void * offsets[5] = {0, 0, 0, 0, 0}; - if (has_normals) { - offsets[0] = offset; - offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); - } - if (has_texcoords) { - offsets[1] = offset; - offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat)); - } - if (has_colors) { - offsets[2] = offset; - offset = (void*)(llong(offset) + vert_count * 4 * sizeof(GLfloat)); - } - if (has_binormals) { - offsets[3] = offset; - offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); - offsets[4] = offset; + if (!simplest) { + if (has_normals) { + offsets[0] = offset; + offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); + } + if (has_texcoords) { + offsets[1] = offset; + offset = (void*)(llong(offset) + vert_count * 2 * sizeof(GLfloat)); + } + if (has_colors) { + offsets[2] = offset; + offset = (void*)(llong(offset) + vert_count * 4 * sizeof(GLfloat)); + } + if (has_binormals) { + offsets[3] = offset; + offset = (void*)(llong(offset) + vert_count * 3 * sizeof(GLfloat)); + offsets[4] = offset; + } } glBindBuffer(GL_ARRAY_BUFFER, buffer_); @@ -147,42 +148,44 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - int loc = prog->attributeLocation("_qgl_Vertex"), loc2 = 0; + int loc = prog->attributeLocation("_qgl_Vertex"); glEnableVertexAttribArray(loc); glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, 0); - loc = prog->attributeLocation("qgl_Normal"); locs << loc; - if (has_normals) { - glEnableVertexAttribArray(loc); - glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[0]); - locs << loc; - } else - glDisableVertexAttribArray(loc); - loc = prog->attributeLocation("qgl_Texture"); - if (has_texcoords) { - glEnableVertexAttribArray(loc); - glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, offsets[1]); - locs << loc; - } else - glDisableVertexAttribArray(loc); - loc = prog->attributeLocation("qgl_Color"); - if (has_colors) { - glEnableVertexAttribArray(loc); - glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 0, offsets[2]); - locs << loc; - } else - glDisableVertexAttribArray(loc); - loc = prog->attributeLocation("qgl_Tangent"); - loc2 = prog->attributeLocation("qgl_Bitangent"); - if (has_binormals) { - glEnableVertexAttribArray(loc); - glEnableVertexAttribArray(loc2); - glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[3]); - glVertexAttribPointer(loc2, 3, GL_FLOAT, 0, 0, offsets[4]); - locs << loc << loc2; - } else { - glDisableVertexAttribArray(loc); - glDisableVertexAttribArray(loc2); + if (!simplest) { + loc = prog->attributeLocation("qgl_Normal"); + if (has_normals) { + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[0]); + locs << loc; + } else + glDisableVertexAttribArray(loc); + loc = prog->attributeLocation("qgl_Texture"); + if (has_texcoords) { + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, offsets[1]); + locs << loc; + } else + glDisableVertexAttribArray(loc); + loc = prog->attributeLocation("qgl_Color"); + if (has_colors) { + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 4, GL_FLOAT, 0, 0, offsets[2]); + locs << loc; + } else + glDisableVertexAttribArray(loc); + loc = prog->attributeLocation("qgl_Tangent"); + int loc2 = prog->attributeLocation("qgl_Bitangent"); + if (has_binormals) { + glEnableVertexAttribArray(loc); + glEnableVertexAttribArray(loc2); + glVertexAttribPointer(loc, 3, GL_FLOAT, 0, 0, offsets[3]); + glVertexAttribPointer(loc2, 3, GL_FLOAT, 0, 0, offsets[4]); + locs << loc << loc2; + } else { + glDisableVertexAttribArray(loc); + glDisableVertexAttribArray(loc2); + } } } else { glEnableClientState(GL_VERTEX_ARRAY); diff --git a/qglview/mainwindow.cpp b/qglview/mainwindow.cpp index 5cb6103..6c2fd85 100644 --- a/qglview/mainwindow.cpp +++ b/qglview/mainwindow.cpp @@ -103,6 +103,10 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() view->camera().flyToDistance(500); //view->camera().setMode(Camera::AimMatrix); Light * l = new Light(view->camera().pos()); + l->light_type = Light::Cone; + l->direction = QVector3D(1., 0.2, -0.2); + l->angle_start = 0.; + l->angle_end = 120.; l->intensity = 1.; //l->decay_linear = 0.2; l->setName("camera"); diff --git a/qglview/qglview.cpp b/qglview/qglview.cpp index 4dba552..b51c599 100644 --- a/qglview/qglview.cpp +++ b/qglview/qglview.cpp @@ -408,13 +408,6 @@ void QGLView::renderSelection() { } -void QGLView::renderShadow() { - glPushMatrix(); - //renderSingleShadow(objects_); - glPopMatrix(); -} - - void QGLView::renderSingleSelection(GLObjectBase & o) { if (!o.isInit()) { o.init(); @@ -444,22 +437,6 @@ void QGLView::renderSingleSelection(GLObjectBase & o) { renderSingleSelection(*i); } -/** -void QGLView::renderSingleShadow(GLObjectBase & o) { - if (!o.isInit()) { - o.init(); - o.loadTextures(); - } - if (!o.visible_) return; - setGLMatrix(start_rp.view_matrix * o.itransform_); - glPolygonMode(GL_FRONT_AND_BACK, o.render_mode != GLObjectBase::View ? o.render_mode : (rmode != GLObjectBase::View ? rmode : GL_FILL)); - glLineWidth(o.line_width > 0. ? o.line_width : lineWidth_); - glPointSize(o.line_width > 0. ? o.line_width : lineWidth_); - o.draw(0, true); - foreach (GLObjectBase * i, o.children_) - renderSingleSelection(*i); -} -*/ void QGLView::collectLights() { lights_.clear(); diff --git a/qglview/qglview.h b/qglview/qglview.h index 5b95234..b0a87f3 100644 --- a/qglview/qglview.h +++ b/qglview/qglview.h @@ -209,7 +209,6 @@ protected: void applyFog(); void renderSelection(); - void renderShadow(); void checkCaps(); void collectLights(); diff --git a/qglview/renderer_deferred_shading.cpp b/qglview/renderer_deferred_shading.cpp index 2ff2f32..139d90c 100644 --- a/qglview/renderer_deferred_shading.cpp +++ b/qglview/renderer_deferred_shading.cpp @@ -104,15 +104,40 @@ void RendererDeferredShading::renderScene() { //glReleaseShaders(); fbo_g.release(); + if (view.isFeatureEnabled(QGLView::qglShadowsEnabled)) { + int sms = view.feature(QGLView::qglShadowsMapSize).toInt(); + glDisable(GL_TEXTURE_1D); + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_CUBE_MAP); + glDisable(GL_MULTISAMPLE); + glDisable(GL_LIGHTING); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_RESCALE_NORMAL); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + //qDebug() << "render shadows"; + for (int i = 0; i < view.lightsCount(); ++i) { + Light * l = view.light(i); + if (l->light_type == Light::Omni) continue; + l->shadow_map.resize(sms, sms); + l->shadow_map.bind(); + glClear(GL_DEPTH_BUFFER_BIT); + renderShadow(l); + l->shadow_map.release(); + } + } + glResetAllTransforms(); - rp.prepare(); glSetLightEnabled(false); + glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); //glBlendFunc(GL_ONE, GL_ONE); glDisableDepth(); - shader_ds_1->bind(); - rp.setUniform(shader_ds_1); + rp.prepare(); //qDebug() << rp.view_matrix; + shader_ds_1->bind(); shader_ds_1->setUniformValue("z_far", GLfloat(view.depthEnd())); shader_ds_1->setUniformValue("z_near", GLfloat(view.depthStart())); shader_ds_1->setUniformValue("t0", 0); @@ -124,6 +149,7 @@ void RendererDeferredShading::renderScene() { shader_ds_1->setUniformValue("back_color", view.backColor()); shader_ds_1->setUniformValue("mat_proji", mproji); shader_ds_1->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height())); + rp.setUniform(shader_ds_1); fbo_g.bindColorTextures(); fbo_g.bindDepthTexture(5); fbo_out.bind(); @@ -131,10 +157,10 @@ void RendererDeferredShading::renderScene() { glClearFramebuffer(Qt::black, false); //QVector lpos; //qDebug() << view_matrix; - int passes = (view.lightsCount() - 1) / lights_per_pass + 1; - if (passes < 1) passes = 1; shader_ds_1->setUniformValue("t_pp", 6); //qDebug() << "render in" << passes << "passes (" << lights_per_pass << ")"; + int passes = (view.lightsCount() - 1) / lights_per_pass + 1; + if (passes < 1) passes = 1; int wi, ri; for (int l = 0; l < passes; ++l) { wi = 1 - l % 2; @@ -321,7 +347,7 @@ void RendererDeferredShading::setupShadersTextures(GLObjectBase & object, GLRend void RendererDeferredShading::setupDSLights(int pass, const QMatrix4x4 & view_matrix) { - int light_start, light_end, lmax; + int light_start, light_end, lmax, shadow_start = 7; light_start = pass * lights_per_pass; light_end = qMin((pass + 1) * lights_per_pass, view.lights().size()); lmax = light_start + lights_per_pass; @@ -331,14 +357,17 @@ void RendererDeferredShading::setupDSLights(int pass, const QMatrix4x4 & view_ma setUniformLight(shader_ds_1, &amb_light, "qgl_AmbientLight"); amb_light.intensity = 0.; QVector lv; - for (int i = light_start; i < light_end; ++i) + for (int i = light_start; i < light_end; ++i) { lv << view.lights()[i]; + glActiveTextureChannel(shadow_start + i - light_start); + glBindTexture(GL_TEXTURE_2D, lv.back()->shadow_map.depthTexture()); + } amb_light.setName("null"); for (int i = light_end; i < lmax; ++i) lv << &amb_light; //QStringList lnl; foreach (Light * l, lv) lnl << l->name(); //qDebug() << " lights" << light_start << "->" << light_end << ", inactive" << (lmax - light_end) << lnl; - setUniformLights(shader_ds_1, lv, view_matrix, view.camera().pos()); + setUniformLights(shader_ds_1, lv, view_matrix, shadow_start); } diff --git a/qglview/shaders/dsl_pass_1.frag b/qglview/shaders/dsl_pass_1.frag index 44343c3..dd1a20e 100644 --- a/qglview/shaders/dsl_pass_1.frag +++ b/qglview/shaders/dsl_pass_1.frag @@ -49,7 +49,6 @@ void calcLight(in int index, in vec3 n, in vec3 v, in vec4 v2) { ndlc = (1. - NdotHs) / NdotHs; der = NdotHs * (sh_mul + ndlc); si += spot * qgl_Light[index].color.rgb * (sh_mul / (der*der) / 3.1416); - //si += der;//dot(n, halfV); } } @@ -69,7 +68,6 @@ void main(void) { vec3 dc = v0.rgb, n = v1.xyz * 2. - vec3(1.); float height = v2.w; li = qgl_AmbientLight.color.rgb * qgl_AmbientLight.intensity; - //li = vec3(0.); si = vec3(0.); float posz = z_near * z_far / (texelFetch(td, tc, 0).r * (z_far - z_near) - z_far); @@ -94,6 +92,6 @@ void main(void) { qgl_FragData[0].rgb = li * dc + si * v2.rgb + v3.rgb + texture(t_pp, tc).rgb; //qgl_FragData[0].rgb = vec3(abs(lpos.xyz - pos.xyz)/10); //qgl_FragData[0].rgb = vec3(ldist/1000); - //qgl_FragData[0].rgb = vec3(length(v4.xyz)/10); + qgl_FragData[0].rgb = vec3(texture(qgl_Light[0].shadow, vec3(qgl_FragTexture.xy, 0.))*1000+0.5); //qgl_FragData[0].a = 0.; }