diff --git a/qglview/glframebuffer.cpp b/qglview/glframebuffer.cpp index 210ff83..cc47e5a 100644 --- a/qglview/glframebuffer.cpp +++ b/qglview/glframebuffer.cpp @@ -53,6 +53,7 @@ void GLFramebuffer::resize(int width, int height) { glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(target_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(target_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, 4); glTexParameteri(target_, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, target_, colors[i], 0); } @@ -76,6 +77,13 @@ void GLFramebuffer::resize(int width, int height) { } +QImage GLFramebuffer::grab() const { + //glReadPixels(0, 0, wid, hei, GL_RGBA, ); + //QImage ret(); + return QImage(); +} + + void GLFramebuffer::bind() { if (is_changed) resize(wid, hei); if (fbo == 0) return; diff --git a/qglview/glframebuffer.h b/qglview/glframebuffer.h index 3b1df80..28efe4c 100644 --- a/qglview/glframebuffer.h +++ b/qglview/glframebuffer.h @@ -35,6 +35,7 @@ public: int width() const {return wid;} int height() const {return hei;} QSize size() const {return QSize(wid, hei);} + QImage grab() const; void resize(int width, int height); void bind(); diff --git a/qglview/globject.cpp b/qglview/globject.cpp index d086e66..f5fd19f 100644 --- a/qglview/globject.cpp +++ b/qglview/globject.cpp @@ -208,6 +208,32 @@ void GLObjectBase::render(int * id, QMap * ids, int sh_id_ } + + +Light::Light(): GLObjectBase(), shadow_map(true, 1, GL_R16F) { + type_ = GLObjectBase::Light; + light_type = Omni; + intensity = 1.; + angle_start = angle_end = 180.; + decay_linear = decay_quadratic = decay_start = 0.; + decay_const = decay_end = 1.; + direction.setZ(1.); +} + + +Light::Light(const QVector3D & p, const QColor & c, GLdouble i): GLObjectBase(), shadow_map(true, 1, GL_R16F) { + type_ = GLObjectBase::Light; + light_type = Omni; + pos_ = p; + intensity = i; + /*color_ = c;*/ + angle_start = angle_end = 180.; + decay_linear = decay_quadratic = decay_start = 0.; + decay_const = decay_end = 1.; + direction.setZ(1.); +} + + GLObjectBase * Light::clone(bool withChildren) { Light * o = new Light(*this); //GLObjectBase::clone(withChildren); @@ -219,12 +245,14 @@ GLObjectBase * Light::clone(bool withChildren) { for (int i = 0; i < children_.size(); ++i) o->addChild(children_[i]->clone(withChildren)); } + o->light_type = light_type; o->direction = direction; + o->angle_start = angle_start; + o->angle_end = angle_end; o->intensity = intensity; o->decay_const = decay_const; o->decay_linear = decay_linear; o->decay_quadratic = decay_quadratic; - o->light_type = light_type; return o; } diff --git a/qglview/globject.h b/qglview/globject.h index d5a2126..cbc60aa 100644 --- a/qglview/globject.h +++ b/qglview/globject.h @@ -214,15 +214,15 @@ class Light: public GLObjectBase { public: enum Type {Omni, Directional, Cone}; - Light(): GLObjectBase(), shadow_map(true, 1, GL_R16F) {type_ = GLObjectBase::Light; light_type = Omni; intensity = 1.; decay_linear = decay_quadratic = angle_spread = angle_decay_exp = decay_start = 0.; decay_const = decay_end = 1.; direction.setZ(1.);} - Light(const QVector3D & p, const QColor & c = Qt::white, GLdouble i = 1.): GLObjectBase(), shadow_map(true, 1, GL_R16F) {type_ = GLObjectBase::Light; light_type = Omni; pos_ = p; intensity = i; /*color_ = c;*/ decay_linear = decay_quadratic = angle_spread = angle_decay_exp = decay_start = 0.; decay_const = decay_end = 1.; direction.setZ(1.);} + Light(); + Light(const QVector3D & p, const QColor & c = Qt::white, GLdouble i = 1.); virtual GLObjectBase * clone(bool withChildren = true); virtual void init() {shadow_map.resize(512, 512); is_init = true;} virtual void draw(QGLShaderProgram * prog, bool simplest = false); QVector3D direction; - GLdouble angle_spread; - GLdouble angle_decay_exp; + GLdouble angle_start; + GLdouble angle_end; GLdouble intensity; GLdouble decay_const; GLdouble decay_linear; diff --git a/qglview/globject_editor.cpp b/qglview/globject_editor.cpp index b427527..689fc6b 100644 --- a/qglview/globject_editor.cpp +++ b/qglview/globject_editor.cpp @@ -74,8 +74,8 @@ void GLObjectEditor::setObject(GLObjectBase * o) { spinLightDecayConst->setValue(l->decay_const); spinLightDecayLinear->setValue(l->decay_linear); spinLightDecayQuadratic->setValue(l->decay_quadratic); - spinLightAngleSpread->setValue(l->angle_spread); - spinLightAngleDecayExp->setValue(l->angle_decay_exp); + spinLightAngleStart->setValue(l->angle_start); + spinLightAngleEnd->setValue(l->angle_end); spinLightDirectionX->setValue(l->direction.x()); spinLightDirectionY->setValue(l->direction.y()); spinLightDirectionZ->setValue(l->direction.z()); @@ -111,9 +111,21 @@ void GLObjectEditor::objectChanged() { l->decay_const = spinLightDecayConst->value(); l->decay_linear = spinLightDecayLinear->value(); l->decay_quadratic = spinLightDecayQuadratic->value(); - l->angle_spread = spinLightAngleSpread->value(); - l->angle_decay_exp = spinLightAngleDecayExp->value(); + l->angle_start = spinLightAngleStart->value(); + l->angle_end = spinLightAngleEnd->value(); l->direction = QVector3D(spinLightDirectionX->value(), spinLightDirectionY->value(), spinLightDirectionZ->value()).normalized(); } emit changed(); } + + +void GLObjectEditor::on_spinLightAngleStart_valueChanged(double v) { + if (spinLightAngleEnd->value() < v) + spinLightAngleEnd->setValue(v); +} + + +void GLObjectEditor::on_spinLightAngleEnd_valueChanged(double v) { + if (spinLightAngleStart->value() > v) + spinLightAngleStart->setValue(v); +} diff --git a/qglview/globject_editor.h b/qglview/globject_editor.h index e787d06..9e78a69 100644 --- a/qglview/globject_editor.h +++ b/qglview/globject_editor.h @@ -39,6 +39,8 @@ protected: private slots: void objectChanged(); + void on_spinLightAngleStart_valueChanged(double v); + void on_spinLightAngleEnd_valueChanged(double v); signals: void changed(); diff --git a/qglview/globject_editor.ui b/qglview/globject_editor.ui index 841c311..146e0a7 100644 --- a/qglview/globject_editor.ui +++ b/qglview/globject_editor.ui @@ -364,6 +364,12 @@ 2 + + 0.100000000000000 + + + 1.000000000000000 + true @@ -390,6 +396,12 @@ 2 + + 0.100000000000000 + + + 1.000000000000000 + true @@ -416,6 +428,12 @@ 2 + + 0.100000000000000 + + + 1.000000000000000 + true @@ -442,6 +460,12 @@ 2 + + 0.100000000000000 + + + 1.000000000000000 + true @@ -450,52 +474,52 @@ - Angle Spread + Angle Start - + 0.000000000000000 - 90.000000000000000 - - - 45.000000000000000 + 180.000000000000000 1 - - false + + 5.000000000000000 + + + 30.000000000000000 - Angle decay exp + Angle End - + 0.000000000000000 - 64.000000000000000 - - - 1.000000000000000 + 180.000000000000000 - 2 + 1 - - true + + 5.000000000000000 + + + 30.000000000000000 @@ -520,6 +544,12 @@ 2 + + 0.100000000000000 + + + 1.000000000000000 + @@ -550,6 +580,12 @@ 2 + + 0.100000000000000 + + + 1.000000000000000 + @@ -566,6 +602,12 @@ 2 + + 0.100000000000000 + + + 1.000000000000000 + @@ -940,7 +982,7 @@ - spinLightAngleSpread + spinLightAngleStart valueChanged(double) GLObjectEditor objectChanged() @@ -956,7 +998,7 @@ - spinLightAngleDecayExp + spinLightAngleEnd valueChanged(double) GLObjectEditor objectChanged() diff --git a/qglview/glrendererbase.cpp b/qglview/glrendererbase.cpp index b06f243..3a4ac15 100644 --- a/qglview/glrendererbase.cpp +++ b/qglview/glrendererbase.cpp @@ -56,8 +56,8 @@ void GLRendererBase::setupLight(const Light & l, int inpass_index, int gl_index) 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_spread); - glLightf(gl_index, GL_SPOT_EXPONENT, l.angle_decay_exp); + glLightf(gl_index, GL_SPOT_CUTOFF, l.angle_end / 2.); + glLightf(gl_index, GL_SPOT_EXPONENT, (1. - piClamp((l.angle_end - l.angle_start) / (l.angle_end + 0.001), 0., 1.)) * 128.); } else { glLightf(gl_index, GL_SPOT_CUTOFF, 180.); } diff --git a/qglview/glshaders.cpp b/qglview/glshaders.cpp index 18b1d83..d377605 100644 --- a/qglview/glshaders.cpp +++ b/qglview/glshaders.cpp @@ -54,9 +54,14 @@ const char qgl_uniform[] = const char qgl_structs[] = "const int qgl_MaxLights = 16;\n" "struct QGLLight {\n" - " vec4 position;\n" " vec4 color;\n" + " vec4 position;\n" + " vec4 direction;\n" " float intensity;\n" + " float startAngle;\n" + " float startAngleCos;\n" + " float endAngle;\n" + " float endAngleCos;\n" " float constantAttenuation;\n" " float linearAttenuation;\n" " float quadraticAttenuation;\n" @@ -192,19 +197,31 @@ void setUniformLights(QGLShaderProgram * prog, const QVector & lights, c } /* " vec3 position;\n" +" vec3 direction;\n" " vec4 color;\n" " float intensity;\n" +" float startAngle;\n" +" float endAngle;\n" " float constantAttenuation;\n" " float linearAttenuation;\n" " float quadraticAttenuation;\n" */ void setUniformLight(QGLShaderProgram * prog, Light * light, QString ulightn, const QMatrix4x4 & mat, const QVector4D & dp) { QMatrix4x4 m = mat * light->worldTransform(); - QVector4D pos(0, 0, 0, 1.); + QVector4D pos(0, 0, 0, 1.), dir(light->direction); pos = m * pos; + dir = (m * dir).normalized(); + double ang_start = light->angle_start / 2., ang_end = light->angle_end / 2.; + if (light->light_type == Light::Omni) + ang_start = ang_end = 180.; //qDebug() << "light" << light->name() << ulightn << pos; prog->setUniformValue((ulightn + ".position").toLatin1().constData(), pos); + prog->setUniformValue((ulightn + ".direction").toLatin1().constData(), dir); prog->setUniformValue((ulightn + ".intensity").toLatin1().constData(), GLfloat(light->intensity)); + prog->setUniformValue((ulightn + ".startAngle").toLatin1().constData(), GLfloat(ang_start)); + prog->setUniformValue((ulightn + ".startAngleCos").toLatin1().constData(), GLfloat(cos(ang_start * deg2rad))); + prog->setUniformValue((ulightn + ".endAngle").toLatin1().constData(), GLfloat(ang_end)); + prog->setUniformValue((ulightn + ".endAngleCos").toLatin1().constData(), GLfloat(cos(ang_end * deg2rad))); prog->setUniformValue((ulightn + ".color").toLatin1().constData(), light->color()); prog->setUniformValue((ulightn + ".constantAttenuation").toLatin1().constData(), GLfloat(light->decay_const)); prog->setUniformValue((ulightn + ".linearAttenuation").toLatin1().constData(), GLfloat(light->decay_linear)); diff --git a/qglview/gltypes.cpp b/qglview/gltypes.cpp index 2b61fb2..1b393d5 100644 --- a/qglview/gltypes.cpp +++ b/qglview/gltypes.cpp @@ -109,9 +109,14 @@ void createGLTexture(GLuint & tex, int width, int height, const GLenum & format, glTexImage2D(target, 0, format, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0); else { int t = GL_UNSIGNED_BYTE; - if (format == GL_RGB32F || format == GL_RGB16F) + int f = GL_RGBA; + if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGBA32F || format == GL_RGBA16F) t = GL_FLOAT; - glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, t, 0); + if (format == GL_RGB32F || format == GL_RGB16F || format == GL_RGB8 || format == GL_RGB) + f = GL_RGB; + glTexImage2D(target, 0, format, width, height, 0, f, t, 0); + //glGenerateMipmap(target); + //qDebug() << "glTexImage2D" << width << height << QString::number(t, 16); } //qDebug() << QString::number(glGetError(), 16); } diff --git a/qglview/glvbo.cpp b/qglview/glvbo.cpp index ce35e6b..051c23e 100644 --- a/qglview/glvbo.cpp +++ b/qglview/glvbo.cpp @@ -142,6 +142,7 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { glBindBuffer(GL_ARRAY_BUFFER, buffer_); if (prog) { + locs.clear(); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -150,21 +151,25 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { 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"); @@ -174,6 +179,7 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { 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); @@ -200,6 +206,8 @@ void GLVBO::draw(GLenum type, QGLShaderProgram * prog, bool simplest) { glDrawArrays(type, 0, vert_count); //qDebug() << "draw" << vert_count << buffer_ << "done"; glBindBuffer(GL_ARRAY_BUFFER, 0); + foreach (int l, locs) + glDisableVertexAttribArray(l); } diff --git a/qglview/glvbo.h b/qglview/glvbo.h index 9c69ee0..9563938 100644 --- a/qglview/glvbo.h +++ b/qglview/glvbo.h @@ -53,6 +53,7 @@ private: void calculateBinormals(); QVector vertices_, normals_, texcoords_, colors_, tangents_, bitangents_; + QVector locs; GLenum usage; GLuint buffer_, va_; int vert_count; diff --git a/qglview/loader_3ds.cpp b/qglview/loader_3ds.cpp index bd446a2..698985b 100644 --- a/qglview/loader_3ds.cpp +++ b/qglview/loader_3ds.cpp @@ -245,9 +245,8 @@ GLObjectBase * loadFrom3DSFile(const QString & filepath, double scale) { globject_cast(co)->direction = (pos.toQVector3D() - co->pos()).normalized(); stream.readRawData((char * )&fl1, sizeof(float)); stream.readRawData((char * )&fl, sizeof(float)); - fl1 /= 2.f; fl /= 2.f; - globject_cast(co)->angle_spread = fl; - globject_cast(co)->angle_decay_exp = (fl - fl1) / fl * 16.; + globject_cast(co)->angle_start = fl1; + globject_cast(co)->angle_end = fl; //qDebug() << "spotlight" << globject_cast(co)->direction << globject_cast(co)->angle_spread; break; case LOADER_3DS_CHUNK_LIGHT_OFF: diff --git a/qglview/loader_dae.cpp b/qglview/loader_dae.cpp index ea3faee..233901b 100644 --- a/qglview/loader_dae.cpp +++ b/qglview/loader_dae.cpp @@ -371,6 +371,10 @@ GLObjectBase * loadFromDAEFile(const QString & filepath, double scale) { sv = dl.firstChildElement("linear_attenuation").firstChild().nodeValue(); if (!sv.isEmpty()) lo->decay_linear = sv.toDouble(); sv = dl.firstChildElement("quadratic_attenuation").firstChild().nodeValue(); if (!sv.isEmpty()) lo->decay_quadratic = sv.toDouble(); ///lo->setTransform(matrices.value(name)); + if (lo->light_type == Light::Cone) { + ml = dn.elementsByTagName("decay_falloff"); if (!ml.isEmpty()) lo->angle_end = ml.at(0).firstChild().nodeValue().toDouble(); + ml = dn.elementsByTagName("hotspot_beam"); if (!ml.isEmpty()) lo->angle_start = ml.at(0).firstChild().nodeValue().toDouble(); + } QVector ol; ol << lo; objects[gid] = ol; diff --git a/qglview/mainwindow.cpp b/qglview/mainwindow.cpp index 9abc689..33d0ff4 100644 --- a/qglview/mainwindow.cpp +++ b/qglview/mainwindow.cpp @@ -32,8 +32,8 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() sel_obj = 0; //spinSliderShine->setDecimals(2); view->setFrameShape(QFrame::NoFrame); - //view->setRenderer(new RendererDeferredShading(view)); - view->setRenderer(new RendererSimple(view)); + view->setRenderer(new RendererDeferredShading(view)); + //view->setRenderer(new RendererSimple(view)); view->setMouseRotateEnabled(true); view->setMouseSelectionEnabled(true); view->setSelectionHaloEnabled(true); @@ -76,8 +76,8 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() //obj = new GLPrimitiveEllipsoid(100, 100, 100, 100, 100);//GLPrimitiveCube(); for (int i = 0; i < obj->childCount(); ++i) if (obj->child(i)->type() == GLObjectBase::Light) { - ((Light*)obj->child(i))->intensity = 1.5; - ((Light*)obj->child(i))->decay_linear = .5; + //((Light*)obj->child(i))->intensity = 1.5; + //((Light*)obj->child(i))->decay_linear = .5; } view->addObject(obj); //obj->child("Box001")->addChild(&(view->camera())); @@ -100,13 +100,13 @@ MainWindow::MainWindow(QWidget * parent): QMainWindow(parent), Ui::MainWindow() view->camera().setPos(QVector3D(10, -20, 20)); view->camera().setAim(QVector3D()); - view->camera().flyToDistance(100); + view->camera().flyToDistance(1000); //view->camera().setMode(Camera::AimMatrix); Light * l = new Light(view->camera().pos()); l->intensity = 0.5; l->decay_linear = 0.2; l->setName("camera"); - view->addObject(l); + //view->addObject(l); view->start(-1); //view->light(0)->light_type = Light::Omni; //obj = loadFrom3DSFile("34.3DS", 0.03); diff --git a/qglview/qglview.cpp b/qglview/qglview.cpp index a0e9ba4..d9c4c3e 100644 --- a/qglview/qglview.cpp +++ b/qglview/qglview.cpp @@ -55,8 +55,8 @@ QGLView::QGLView(QWidget * parent): QGraphicsView(parent), fbo_selection(3) { //lmode = Simple; shader_select = shader_halo = 0; cur_luminance = 1.; - accom_time = 32.; - accom_max_speed = 0.1; + accom_time = 16.; + accom_max_speed = 0.2; mouse_first = mouseSelect_ = accomodation_ = hoverHalo_ = selectionHalo_ = true; fogEnabled_ = is_init = grabMouse_ = mouseRotate_ = mouseThis_ = shaders_bind = shadows_ = shadows_soft = dynamic_reflections = hdr_ = bloom_ = msaa_ = fxaa_ = changed_ = false; rmode = GLObjectBase::Fill; @@ -304,6 +304,10 @@ void QGLView::paintGL() { qDebug() << QRect(downPos, lastPos).normalized(); } + glReleaseShaders(); + glResetAllTransforms(); + glReleaseFramebuffer(); + emit glPainting(); /*releaseShaders(); diff --git a/qglview/renderer_deferred_shading.cpp b/qglview/renderer_deferred_shading.cpp index e8be085..e0c846f 100644 --- a/qglview/renderer_deferred_shading.cpp +++ b/qglview/renderer_deferred_shading.cpp @@ -17,14 +17,40 @@ */ #include "renderer_deferred_shading.h" +#include -RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_), fbo_g(4, true, GL_RGBA16F), fbo_out(2, GL_RGBA16F) { - shader_fxaa = shader_ds_0 = shader_ds_1 = 0; +RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_), +fbo_g(4, true, GL_RGBA16F), fbo_out(2, false, GL_RGB16F), fbo_hsmall(1, false, GL_RGB16F) { + shader_fxaa = shader_ds_0 = shader_ds_1 = shader_hdr = shader_small = 0; + lights_per_pass = 2; + exposure_ = 1.; + df = new QWidget(); + df->setLayout(new QBoxLayout(QBoxLayout::TopToBottom)); + label_exp = new QLabel(); + label_exp_step = new QLabel(); + df->layout()->addWidget(label_exp); + df->layout()->addWidget(label_exp_step); + QPalette pal(df->palette()); + pal.setBrush(QPalette::Window, QColor(255, 255, 255, 192)); + df->setPalette(pal); + if (view_) + view_->addObject(df); +} + + +RendererDeferredShading::~RendererDeferredShading() { + if (shader_fxaa != 0) delete shader_fxaa; + if (shader_ds_0 != 0) delete shader_ds_0; + if (shader_ds_1 != 0) delete shader_ds_1; + if (shader_hdr != 0) delete shader_hdr; + if (shader_small != 0) delete shader_small; + delete df; } void RendererDeferredShading::renderScene() { + //qDebug() << lights_per_pass; QMatrix4x4 mproji = rp.proj_matrix_i; QMatrix4x4 mview = rp.view_matrix; corner_dirs[0] = (QVector4D(-1, -1, 1, 1) * rp.viewproj_matrix).normalized(); @@ -48,7 +74,7 @@ void RendererDeferredShading::renderScene() { glActiveTextureChannel(0); } glClearFramebuffer(QColor(0, 0, 0, 0)); - //glEnable(GL_TEXTURE_2D); + glDisable(GL_RESCALE_NORMAL); glEnableDepth(); shader_ds_0->bind(); rp.setUniform(shader_ds_0); @@ -61,7 +87,7 @@ void RendererDeferredShading::renderScene() { shader_ds_0->setUniformValue("dt", QVector2D(1. / view.viewport()->width(), 1. / view.viewport()->height())); renderObjects(GLObjectBase::Solid, 0, shader_ds_0, true, false, false); //glReleaseShaders(); - //fbo.release(); + fbo_g.release(); glResetAllTransforms(); rp.prepare(); @@ -89,28 +115,72 @@ void RendererDeferredShading::renderScene() { glClearFramebuffer(Qt::black, false); //QVector lpos; //qDebug() << view_matrix; - int passes = (view.lightsCount() - 1) / 16 + 1; + int passes = (view.lightsCount() - 1) / lights_per_pass + 1; if (passes < 1) passes = 1; shader_ds_1->setUniformValue("t_pp", 5); - //qDebug() << "render in" << passes << "passes"; + //qDebug() << "render in" << passes << "passes (" << lights_per_pass << ")"; + int wi, ri; for (int l = 0; l < passes; ++l) { - int wi = 1 - l % 2, ri = l % 2; + wi = 1 - l % 2; + ri = l % 2; //qDebug() << " pass" << l << "read from" << ri << "write to" << wi; glActiveTextureChannel(5); glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri)); fbo_out.setWriteBuffer(wi); - setupDSLights(l, 16, mview); + setupDSLights(l, mview); //shader_ds_1->setUniformValue("lightsCount", cplc); glDrawQuad(shader_ds_1); //renderObjects(GLObjectBase::Solid, l, 0, true, true, view.isFogEnabled()); //renderObjects(GLObjectBase::Transparent, l, 0, true, true, view.isFogEnabled()); - glFinish(); + //glFinish(); //break; } fbo_out.release(); - glReleaseShaders(); + wi = 1 - passes % 2; + ri = passes % 2; glActiveTextureChannel(0); - glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(passes % 2)); + glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri)); + + fbo_hsmall.bind(); + fbo_hsmall.setWriteBuffer(0); + shader_small->bind(); + shader_small->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); + shader_small->setUniformValue("t0", 0); + glDrawQuad(shader_small); + hcontent.resize(fbo_hsmall.width() * fbo_hsmall.height()); + glReadPixels(0, 0, fbo_hsmall.width(), fbo_hsmall.height(), GL_RGB, GL_FLOAT, hcontent.data()); + GLfloat max[3] = {0.,0.,0.};//min[3] = {10000.,10000.,10000.}, ; + for (int i = 0; i < hcontent.size(); ++i) { + //if (min[0] > hcontent[i].x) min[0] = hcontent[i].x; + if (max[0] < hcontent[i].x) max[0] = hcontent[i].x; + //if (min[1] > hcontent[i].y) min[1] = hcontent[i].y; + if (max[1] < hcontent[i].y) max[1] = hcontent[i].y; + //if (min[2] > hcontent[i].z) min[2] = hcontent[i].z; + if (max[2] < hcontent[i].z) max[2] = hcontent[i].z; + } + GLfloat mluma = (0.299 * max[0]) + (0.587 * max[1]) + (0.114 * max[2]); + double nexp = mluma / 16., dexp = nexp - exposure_, mestep = exposure_ * view.accomodationMaxSpeed(); + dexp /= view.accomodationTime(); + if (dexp > 0. && dexp > mestep/4) dexp = mestep/4; + if (dexp < 0. && dexp < -mestep) dexp = -mestep; + exposure_ += dexp; + label_exp->setText(QString("exposure: %1").arg(exposure_)); + label_exp_step->setText(QString("d_exposure: %1").arg(dexp)); + //qDebug() << min[0] << max[0] << min[1] << max[1] << min[2] << max[2]; + fbo_hsmall.release(); + + //glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri)); + fbo_out.bind(); + fbo_out.setWriteBuffer(wi); + shader_hdr->bind(); + shader_hdr->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); + shader_hdr->setUniformValue("t0", 0); + shader_hdr->setUniformValue("exposure", GLfloat(1./exposure_)); + glDrawQuad(shader_hdr); + fbo_out.release(); + + glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(wi)); + glReleaseShaders(); if (view.isFXAAEnabled()) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -127,14 +197,16 @@ void RendererDeferredShading::renderScene() { void RendererDeferredShading::init(int width, int height) { - fbo_g.resize(width, height); - fbo_out.resize(width, height); + resize(width, height); } void RendererDeferredShading::resize(int width, int height) { fbo_g.resize(width, height); fbo_out.resize(width, height); + fbo_hsmall.resize(width / 16, height / 16); + view.setSceneRect(QRect(0, 0, width, height)); /// WARNING + //df->move(-width / 2, -height / 2); } @@ -142,10 +214,13 @@ void RendererDeferredShading::reloadShaders() { if (shader_fxaa == 0) shader_fxaa = new QGLShaderProgram(view.context()); if (shader_ds_0 == 0) shader_ds_0 = new QGLShaderProgram(view.context()); if (shader_ds_1 == 0) shader_ds_1 = new QGLShaderProgram(view.context()); - //if (shader_ds_0 == 0) shader_ds_0 = new QGLShaderProgram(view.context()); + if (shader_hdr == 0) shader_hdr = new QGLShaderProgram(view.context()); + if (shader_small == 0) shader_small = new QGLShaderProgram(view.context()); loadShaders(shader_fxaa, "FXAA", "shaders"); loadShaders(shader_ds_0, "dsl_pass_0", "shaders"); loadShaders(shader_ds_1, "dsl_pass_1", "shaders"); + loadShaders(shader_hdr, "hdr", "shaders"); + loadShaders(shader_small, "downscale", "shaders"); } @@ -162,7 +237,7 @@ void RendererDeferredShading::setupShadersTextures(GLObjectBase & object, GLRend } -void RendererDeferredShading::setupDSLights(int pass, int lights_per_pass, const QMatrix4x4 & view_matrix) { +void RendererDeferredShading::setupDSLights(int pass, const QMatrix4x4 & view_matrix) { int light_start, light_end, lmax; light_start = pass * lights_per_pass; light_end = qMin((pass + 1) * lights_per_pass, view.lights().size()); diff --git a/qglview/renderer_deferred_shading.h b/qglview/renderer_deferred_shading.h index 59d407a..e24f3b0 100644 --- a/qglview/renderer_deferred_shading.h +++ b/qglview/renderer_deferred_shading.h @@ -20,12 +20,13 @@ #define RENDERER_DEFERRED_SHADING_H #include "qglview.h" +#include class RendererDeferredShading: public GLRendererBase { public: RendererDeferredShading(QGLView * view); - virtual ~RendererDeferredShading() {if (shader_fxaa != 0) delete shader_fxaa;} + virtual ~RendererDeferredShading(); virtual void renderScene(); @@ -35,19 +36,24 @@ protected: void reloadShaders(); void setupShadersTextures(GLObjectBase & object, RenderingParameters & rp); void setupShadersLights(int lights_count) {cplc = lights_count;} - void setupDSLights(int pass, int lights_per_pass, const QMatrix4x4 & view_matrix); + void setupDSLights(int pass, const QMatrix4x4 & view_matrix); void setupAmbientLight(const QColor & a, bool first_pass); private: - int cplc; - GLFramebuffer fbo_g, fbo_out; - QGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1; + int cplc, BUG[8], lights_per_pass; + double exposure_; + GLFramebuffer fbo_g, fbo_out, fbo_hsmall; + QGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1, * shader_hdr, * shader_small; QMatrix4x4 pm, mvm, mvpm, pim, mvim, mvpim; QMatrix3x3 nm; QVector4D corner_dirs[4]; + QVector hcontent; Light amb_light; + QWidget * df; + QLabel * label_exp, * label_exp_step; + }; #endif // RENDERER_DEFERRED_SHADING_H diff --git a/qglview/renderer_simple.cpp b/qglview/renderer_simple.cpp index 4b87925..402a469 100644 --- a/qglview/renderer_simple.cpp +++ b/qglview/renderer_simple.cpp @@ -58,6 +58,7 @@ void RendererSimple::renderScene() { fbo.setWriteBuffer(0); glClearFramebuffer(); } + glEnable(GL_RESCALE_NORMAL); for (int l = 0; l < passes; ++l) { if (passes > 1) fbo.setWriteBuffer(1); if (l == 0) { diff --git a/qglview/shaders/downscale.frag b/qglview/shaders/downscale.frag new file mode 100644 index 0000000..0cef038 --- /dev/null +++ b/qglview/shaders/downscale.frag @@ -0,0 +1,7 @@ +#version 150 + +uniform sampler2D t0; + +void main(void) { + qgl_FragData[0].rgb = textureLod(t0, qgl_FragTexture.xy, 3).rgb; +} diff --git a/qglview/shaders/downscale.vert b/qglview/shaders/downscale.vert new file mode 100644 index 0000000..6bc001e --- /dev/null +++ b/qglview/shaders/downscale.vert @@ -0,0 +1,6 @@ +#version 150 + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); +} diff --git a/qglview/shaders/dsl_pass_0.frag b/qglview/shaders/dsl_pass_0.frag index 70d68b4..9089593 100644 --- a/qglview/shaders/dsl_pass_0.frag +++ b/qglview/shaders/dsl_pass_0.frag @@ -15,11 +15,11 @@ void main(void) { float z = pos.w;//((z_near / (z_near-z_far)) * z_far) / (pos.w - (z_far / (z_far-z_near))); vec4 dc = qgl_FragColor; vec2 tc = qgl_FragTexture.xy; - float hei = dot(texture2D(qgl_Material.map_relief.map, tc).rgb, luma) * qgl_Material.map_relief.amount + qgl_Material.map_relief.offset; + float hei = dot(texture(qgl_Material.map_relief.map, tc).rgb, luma) * qgl_Material.map_relief.amount + qgl_Material.map_relief.offset; //if (acc_fog) dc.xyz = mix(dc.rgb, gl_Fog.color.rgb, fogCoord); vec3 n, dn; - dn = (texture2D(qgl_Material.map_normal.map, tc).rgb - vec3(0.5, 0.5, 1.)) * qgl_Material.map_normal.amount + qgl_Material.map_normal.offset; + dn = (texture(qgl_Material.map_normal.map, tc).rgb - vec3(0.5, 0.5, 1.)) * qgl_Material.map_normal.amount + qgl_Material.map_normal.offset; //float tx = dn.x; dn.y = -dn.y; //dn.y = tx; @@ -34,12 +34,12 @@ void main(void) { dpm = dpm * gl_ModelViewProjectionMatrixInverse; dpm += */ //tc += 1+et.xy * hei/10;// / et.z; - dc *= texture2D(qgl_Material.map_diffuse.map, tc) * qgl_Material.map_diffuse.amount + qgl_Material.map_diffuse.offset; + dc *= texture(qgl_Material.map_diffuse.map, tc) * qgl_Material.map_diffuse.amount + qgl_Material.map_diffuse.offset; - vec4 spec = texture2D(qgl_Material.map_specular.map, tc) * qgl_Material.map_specular.amount + qgl_Material.map_specular.offset; + vec4 spec = texture(qgl_Material.map_specular.map, tc) * qgl_Material.map_specular.amount + qgl_Material.map_specular.offset; spec *= qgl_Material.color_specular; - vec4 specularity = texture2D(qgl_Material.map_specularity.map, tc) * qgl_Material.map_specularity.amount + qgl_Material.map_specularity.offset; - vec4 self = texture2D(qgl_Material.map_self_illumination.map, tc) * qgl_Material.map_self_illumination.amount + qgl_Material.map_self_illumination.offset; + vec4 specularity = texture(qgl_Material.map_specularity.map, tc) * qgl_Material.map_specularity.amount + qgl_Material.map_specularity.offset; + vec4 self = texture(qgl_Material.map_self_illumination.map, tc) * qgl_Material.map_self_illumination.amount + qgl_Material.map_self_illumination.offset; self *= qgl_Material.color_self_illumination; qgl_FragData[0] = vec4(dc.rgb, z); diff --git a/qglview/shaders/dsl_pass_0.vert b/qglview/shaders/dsl_pass_0.vert index 6877795..8d0d34a 100644 --- a/qglview/shaders/dsl_pass_0.vert +++ b/qglview/shaders/dsl_pass_0.vert @@ -25,5 +25,6 @@ void main(void) { //tp /= tp.w; src_normal = normalize(vec3(pos.xy * dt * 2., 0)); pos.w = tp.w; + //pos *= pos.w; gl_Position = tp;//ftransform(); } diff --git a/qglview/shaders/dsl_pass_1.frag b/qglview/shaders/dsl_pass_1.frag index 70d2473..79e98da 100644 --- a/qglview/shaders/dsl_pass_1.frag +++ b/qglview/shaders/dsl_pass_1.frag @@ -30,11 +30,13 @@ void calcLight(in int index, in vec3 n, in vec3 v, in vec4 v2) { NdotH = max(dot(n, halfV), 0.); spot = step(0., NdotL) * qgl_Light[index].intensity; if (NdotL > 0.) { - /*if (gl_LightSource[index].spotCutoff < 180.) { - spot = max(dot(-ldir, gl_LightSource[index].spotDirection.xyz), 0.); - spot *= step(gl_LightSource[index].spotCosCutoff, spot); - spot = pow(spot, (gl_LightSource[index].spotExponent + 0.001)); - }*/ + if (qgl_Light[index].endAngle <= 90.) { + float scos = max(dot(-ldir, qgl_Light[index].direction.xyz), 0.); + spot *= scos * step(qgl_Light[index].endAngleCos, scos); + //spot = clamp(scos / (-qgl_Light[index].endAngleCos + qgl_Light[index].startAngleCos + 0.0001),0,1); + spot *= smoothstep(qgl_Light[index].endAngleCos, qgl_Light[index].startAngleCos, scos); + //spot = pow(spot, (qgl_Light[index].spotExponent + 0.001)); + } spot /= (qgl_Light[index].constantAttenuation + ldist * (qgl_Light[index].linearAttenuation + ldist * qgl_Light[index].quadraticAttenuation)); ///li += spot * gl_LightSource[index].diffuse.rgb * light_diffuse(0, ldir, n); //si += spot * qgl_Light[index].color.rgb * sh_mul * light_specular(0, ldir, n, halfV, v, sh_pow); @@ -72,6 +74,7 @@ void main(void) { pos.xy *= v3.w; pos.z = posz; pos.xyz += n * height; + //pos.xyz = v3.xyz; //pos = v3; //pos = vec4(sp, 0, 1.) * mat_proji; //pos *= v0.w; @@ -79,37 +82,15 @@ void main(void) { //pos.xy *= 10.; //pos.z = v0.w; vec3 v = normalize(-pos.xyz); + sh_pow = 1. / max((1. - v1.w), 0.0001); sh_mul = max(1. - v1.w, 0.0001); - //for (int i = 0; i < 16; ++i) - calcLight(7, n, v, v2); - /*if (lightsCount > 0) { - calcLight(0, n, v, v2); - if (lightsCount > 1) { - calcLight(1, n, v, v2); - if (lightsCount > 2) { - calcLight(2, n, v, v2); - if (lightsCount > 3) { - calcLight(3, n, v, v2); - if (lightsCount > 4) { - calcLight(4, n, v, v2); - if (lightsCount > 5) { - calcLight(5, n, v, v2); - if (lightsCount > 6) { - calcLight(6, n, v, v2); - if (lightsCount > 7) { - calcLight(7, n, v, v2); - } - } - } - } - } - } - } - }*/ - qgl_FragData[0].rgb = li * dc + si * v2.rgb + v3.rgb + texture2D(t_pp, tc).rgb; + for (int i = 0; i < 16; ++i) + calcLight(i, n, v, v2); + + 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 = texture2D(t_pp, tc).rgb; - //qgl_FragData[0].rgb = vec3(pow(NdotH,100)*2); + //qgl_FragData[0].rgb = si.rgb; + //qgl_FragData[0].rgb = (v0.rgb)/2; //qgl_FragData[0].a = 0.; } diff --git a/qglview/shaders/hdr.frag b/qglview/shaders/hdr.frag new file mode 100644 index 0000000..8692043 --- /dev/null +++ b/qglview/shaders/hdr.frag @@ -0,0 +1,27 @@ +#version 150 + +uniform sampler2D t0; +uniform float exposure; + +float tA = 0.15; +float tB = 0.50; +float tC = 0.10; +float tD = 0.20; +float tE = 0.02; +float tF = 0.30; +float tW = 11.2; + +vec3 Uncharted2Tonemap(vec3 x) { + return ((x*(tA*x+tC*tB)+tD*tE)/(x*(tA*x+tB)+tD*tF))-tE/tF; +} + +void main(void) { + vec3 inColor = texture(t0, qgl_FragTexture.xy).rgb; + inColor *= exposure; + float ExposureBias = 1; + vec3 curr = Uncharted2Tonemap(ExposureBias*inColor); + vec3 whiteScale = 1 / Uncharted2Tonemap(vec3(tW)); + vec3 color = curr * whiteScale; + vec3 retColor = pow(color, vec3(1 / 2.2)); + qgl_FragData[0].rgb = retColor; +} diff --git a/qglview/shaders/hdr.vert b/qglview/shaders/hdr.vert new file mode 100644 index 0000000..6bc001e --- /dev/null +++ b/qglview/shaders/hdr.vert @@ -0,0 +1,6 @@ +#version 150 + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); +}