diff --git a/qglview/data/room.dae.qgl b/qglview/data/room.dae.qgl index 364dd77..80bac14 100644 Binary files a/qglview/data/room.dae.qgl and b/qglview/data/room.dae.qgl differ diff --git a/qglview/icons/document-save-all.png b/qglview/icons/document-save-all.png new file mode 100644 index 0000000..3e40997 Binary files /dev/null and b/qglview/icons/document-save-all.png differ diff --git a/qglview/main.cpp b/qglview/main.cpp index 046b7b7..e1fe0ea 100644 --- a/qglview/main.cpp +++ b/qglview/main.cpp @@ -105,5 +105,9 @@ int main(int argc, char ** argv) { //a.setWindowIcon(QIcon(":/icons/peri4_paint.png")); MainWindow w; w.show(); + QStringList al(a.arguments()); + al.pop_front(); + foreach (QString s, al) + w.loadFile(s); return a.exec(); } diff --git a/qglview/mainwindow.cpp b/qglview/mainwindow.cpp index 84afdba..d7f325d 100644 --- a/qglview/mainwindow.cpp +++ b/qglview/mainwindow.cpp @@ -148,11 +148,11 @@ void MainWindow::importFile(const QString & path) { QApplication::setOverrideCursor(Qt::WaitCursor); QFileInfo fi(path); GLObjectBase * o = 0; - if (fi.completeSuffix().toLower() == "qgl") o = loadFromQGLFile(path); - if (fi.completeSuffix().toLower() == "ase") o = loadFromASEFile(path); - if (fi.completeSuffix().toLower() == "3ds") o = loadFrom3DSFile(path); - if (fi.completeSuffix().toLower() == "obj") o = loadFromOBJFile(path); - if (fi.completeSuffix().toLower() == "dae") o = loadFromDAEFile(path); + if (fi.suffix().toLower() == "qgl") o = loadFromQGLFile(path); + if (fi.suffix().toLower() == "ase") o = loadFromASEFile(path); + if (fi.suffix().toLower() == "3ds") o = loadFrom3DSFile(path); + if (fi.suffix().toLower() == "obj") o = loadFromOBJFile(path); + if (fi.suffix().toLower() == "dae") o = loadFromDAEFile(path); QApplication::restoreOverrideCursor(); if (!o) { QMessageBox::critical(this, "Import", "Can`t load " + path + "!"); @@ -251,6 +251,17 @@ void MainWindow::on_actionSave_triggered() { } +void MainWindow::on_actionSaveSelected_triggered() { + if (!sel_obj) return; + QString f = QFileDialog::getSaveFileName(this, "Select file", prev_path, "QGLView(*.qgl)"); + if (f.isEmpty()) return; + if (f.right(4).toLower() != ".qgl") + f += ".qgl"; + prev_path = f; + saveToQGLFile(f, sel_obj); +} + + void MainWindow::on_actionOpen_triggered() { QString f = QFileDialog::getOpenFileName(this, "Select file", prev_path, "Supported types(*.qgl *.ase *.3ds *.obj *.dae);;" "QGLView(*.qgl);;" @@ -281,12 +292,15 @@ void MainWindow::on_view_keyEvent(Qt::Key k, Qt::KeyboardModifiers m) { void MainWindow::on_treeObjects_itemClicked(QTreeWidgetItem * ti, int col) { ((GLObjectBase*)(ti->data(0, Qt::UserRole).toULongLong()))->select(); + if (sel_obj->type() == GLObjectBase::glCamera) + view->setCamera(*(Camera*)sel_obj); } void MainWindow::objectsTreeChanged() { treeObjects->clear(); makeObjetTree(&(view->rootObject()), treeObjects->invisibleRootItem()); + treeObjects->expandAll(); } diff --git a/qglview/mainwindow.h b/qglview/mainwindow.h index 51263de..2ce78b9 100644 --- a/qglview/mainwindow.h +++ b/qglview/mainwindow.h @@ -46,12 +46,13 @@ public: MainWindow(QWidget * parent = 0); ~MainWindow(); + void loadFile(const QString & path); + private: // Qt`s overloaded void changeEvent(QEvent * e); void timerEvent(QTimerEvent * ); - void loadFile(const QString & path); void importFile(const QString & path); void makeObjetTree(const GLObjectBase * o, QTreeWidgetItem * ti); @@ -102,6 +103,7 @@ private slots: void on_actionReset_triggered(); void on_actionImport_triggered(); void on_actionSave_triggered(); + void on_actionSaveSelected_triggered(); void on_actionOpen_triggered(); void on_view_glKeyPressEvent(QKeyEvent * e); diff --git a/qglview/mainwindow.ui b/qglview/mainwindow.ui index ceac21f..0f35764 100644 --- a/qglview/mainwindow.ui +++ b/qglview/mainwindow.ui @@ -22,7 +22,7 @@ 2 - 0 + 0 @@ -490,7 +490,7 @@ 1.000000000000000 - 2048.000000000000000 + 128.000000000000000 8.000000000000000 @@ -896,6 +896,11 @@ false + + + + + @@ -913,6 +918,7 @@ + @@ -938,6 +944,9 @@ Import ... + + Ctrl+I + @@ -947,15 +956,21 @@ Open ... + + Ctrl+O + - :/icons/document-save-.png:/icons/document-save-.png + :/icons/document-save-all.png:/icons/document-save-all.png Save ... + + Ctrl+S + @@ -965,6 +980,24 @@ Reset + + Ctrl+N + + + + + + :/icons/document-save-.png:/icons/document-save-.png + + + Save selected ... + + + Save selected + + + Ctrl+Shift+S + diff --git a/qglview/qglview.qrc b/qglview/qglview.qrc index 169e46e..01dd2ea 100644 --- a/qglview/qglview.qrc +++ b/qglview/qglview.qrc @@ -1,5 +1,6 @@ + icons/document-save-all.png icons/document-new.png icons/document-import.png icons/dialog-close.png diff --git a/qglview/renderer_deferred_shading.cpp b/qglview/renderer_deferred_shading.cpp index 0276708..5d7221e 100644 --- a/qglview/renderer_deferred_shading.cpp +++ b/qglview/renderer_deferred_shading.cpp @@ -21,7 +21,7 @@ RendererDeferredShading::RendererDeferredShading(QGLView * view_): GLRendererBase(view_), -fbo_g(5, true, GL_RGBA16F), fbo_out(3, false, GL_RGB16F), fbo_hsmall(1, false, GL_RGB16F) { +fbo_g(5, true, GL_RGBA16F), fbo_out(3, false, GL_RGBA16F), fbo_hsmall(1, false, GL_RGB16F) { shaders << ShaderPair("FXAA", &shader_fxaa) << ShaderPair("dsl_pass_0", &shader_ds_0) << ShaderPair("dsl_pass_1", &shader_ds_1) @@ -32,7 +32,9 @@ fbo_g(5, true, GL_RGBA16F), fbo_out(3, false, GL_RGB16F), fbo_hsmall(1, false, G << ShaderPair("fbo_add", &shader_fbo_add) << ShaderPair("motion_blur", &shader_motion_blur) << ShaderPair("shadow", &shader_shadow) - << ShaderPair("ssr", &shader_ssr); + << ShaderPair("ssr", &shader_ssr) + << ShaderPair("ssr_blur", &shader_ssr_blur) + << ShaderPair("ssr_merge", &shader_ssr_merge); for (int i = 0; i < shaders.size(); ++i) *(shaders[i].second) = 0; lights_per_pass = 8; @@ -66,7 +68,7 @@ void RendererDeferredShading::renderScene() { QMatrix4x4 mproji = rp.proj_matrix_i; QMatrix4x4 mview = rp.view_matrix; QMatrix4x4 mviewi = rp.view_matrix_i; - QMatrix4x4 mviewproji = (mview * mproj).inverted(); + QMatrix4x4 mviewproji = (mproj * mview).inverted(); QMatrix4x4 moffset = view.camera().offsetMatrix(); QMatrix4x4 moffseti = moffset.inverted(); rp.prev_proj_matrix = prev_proj; @@ -196,21 +198,62 @@ void RendererDeferredShading::renderScene() { glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri)); if (view.isFeatureEnabled(QGLView::qglDynamicReflectionsEnabled)) { - fbo_out.setWriteBuffer(wi); + fbo_out.setWriteBuffer(2); + glActiveTextureChannel(0); + glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//_MIPMAP_LINEAR); + //glGenerateMipmap(GL_TEXTURE_2D); glActiveTextureChannel(1); glBindTexture(GL_TEXTURE_2D, fbo_g.colorTexture(0)); glActiveTextureChannel(2); glBindTexture(GL_TEXTURE_2D, fbo_g.colorTexture(1)); shader_ssr->bind(); shader_ssr->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); - shader_ssr->setUniformValue("dt", QVector2D(1. / fbo_out.width(), 1. / fbo_out.height())); + shader_ssr->setUniformValue("z_far", GLfloat(view.depthEnd())); + shader_ssr->setUniformValue("z_near", GLfloat(view.depthStart())); + shader_ssr->setUniformValue("mat_proj", mproj); shader_ssr->setUniformValue("t0", 1); shader_ssr->setUniformValue("t1", 2); shader_ssr->setUniformValue("ts", 0); //shader_ssr->setUniformValue("ts", 1); shader_ssr->setUniformValue("factor", GLfloat(view.feature(QGLView::qglMotionBlurFactor).toDouble())); shader_ssr->setUniformValue("steps", view.feature(QGLView::qglMotionBlurSteps).toInt()); - glDrawQuad(shader_ssr); + glDrawQuad(shader_ssr, corner_dirs); + + shader_ssr_blur->bind(); + shader_ssr_blur->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); + shader_ssr_blur->setUniformValue("dt", QVector2D(1. / fbo_out.width(), 1. / fbo_out.height())); + shader_ssr_blur->setUniformValue("t0", 0); + int passes = 4; + int crad = 1; + int lri = 2, lwi = wi, lms = ri; + glActiveTextureChannel(0); + for (int p = 0; p < passes; ++p) { + glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(lri)); + fbo_out.setWriteBuffer(lwi); + shader_ssr_blur->setUniformValue("radius", GLfloat(crad)); + glDrawQuad(shader_ssr_blur); + piSwap(lwi, lri); + crad *= 2; + } + wi = lri; + ri = 1 - lms; + qDebug() << wi << ri << lms; + + glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(wi)); + glActiveTextureChannel(1); + glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(lms)); + shader_ssr_merge->bind(); + shader_ssr_merge->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); + shader_ssr_merge->setUniformValue("t0", 0); + shader_ssr_merge->setUniformValue("ts", 1); + fbo_out.setWriteBuffer(ri); + glDrawQuad(shader_ssr_blur); + wi = ri; + ri = 1 - ri; + //piSwap(wi, ri); + glActiveTextureChannel(0); glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(wi)); piSwap(wi, ri); @@ -278,8 +321,8 @@ void RendererDeferredShading::renderScene() { fbo_out.setWriteBuffer(2); fbo_out.setReadBuffer(ri); glBlitFramebuffer(0, 0, fbo_out.width(), fbo_out.height(), 0, 0, fbo_out.width(), fbo_out.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); - QTime tm; - tm.restart(); + //QTime tm; + //tm.restart(); fbo_out.setWriteBuffer(wi); shader_bloom_0->bind(); shader_bloom_0->setUniformValue("qgl_ModelViewProjectionMatrix", QMatrix4x4()); @@ -307,7 +350,7 @@ void RendererDeferredShading::renderScene() { piSwap(wi, ri); crad *= 2; } - qDebug() << tm.elapsed(); + //qDebug() << tm.elapsed(); fbo_out.setWriteBuffer(wi); glActiveTextureChannel(0); glBindTexture(GL_TEXTURE_2D, fbo_out.colorTexture(ri)); diff --git a/qglview/renderer_deferred_shading.h b/qglview/renderer_deferred_shading.h index 55a1210..8d31c91 100644 --- a/qglview/renderer_deferred_shading.h +++ b/qglview/renderer_deferred_shading.h @@ -47,7 +47,7 @@ private: GLFramebuffer fbo_g, fbo_out, fbo_hsmall; QGLShaderProgram * shader_fxaa, * shader_ds_0, * shader_ds_1, * shader_hdr, * shader_small; QGLShaderProgram * shader_bloom_0, * shader_bloom_1, * shader_motion_blur, * shader_fbo_add; - QGLShaderProgram * shader_shadow, * shader_ssr; + QGLShaderProgram * shader_shadow, * shader_ssr, * shader_ssr_blur, * shader_ssr_merge; QVector shaders; QMatrix4x4 prev_view, prev_proj; diff --git a/qglview/shaders/ssr.frag b/qglview/shaders/ssr.frag index b14003e..4717c67 100644 --- a/qglview/shaders/ssr.frag +++ b/qglview/shaders/ssr.frag @@ -1,17 +1,50 @@ #version 150 -uniform sampler2D t0, t1, ts; +uniform sampler2D t0, t1, ts, tbs; uniform float z_near, z_far; +uniform mat4 mat_proj; +uniform vec3 cam_aim, cam_pos; + +in vec3 view_dir; void main(void) { ivec2 tc = ivec2(gl_FragCoord.xy); - vec2 sp = qgl_FragTexture.xy; vec4 v0 = texelFetch(t0, tc, 0), v1 = texelFetch(t1, tc, 0), vs = texelFetch(ts, tc, 0); + vec3 sp = vec3(qgl_FragTexture.xy, v0.w); + vec2 tsp; + vec4 pos; + pos.w = 1; + pos.xyz = view_dir * v0.w; + vec4 spos = pos; + vec4 tpos; + vec3 dc = v0.rgb, n = v1.xyz * 2. - vec3(1.); - vec3 vd = vec3(0, 0, 1); + vec3 vd = -normalize(vec3(-view_dir.xy, view_dir.z)); vec3 rn = reflect(vd, n); - float coeff = clamp(dot(vd, rn), 0, 1); - vec3 rvs = texture(ts, sp - rn.xy/v0.w).rgb; - qgl_FragData[0].rgb = mix(vs.rgb, rvs, coeff); - //qgl_FragData[0].rgb = vec3(v0.w/10); + //rn.z += 1.; + float coeff = clamp(1.-(dot(vec3(0,0,1), n)), 0, 1), cz = v0.w; + coeff = coeff*coeff; + coeff = coeff*coeff; + + rn.z = -rn.z; + int i = 0; + vec4 tv0; + float l = z_far * 0.5; + pos.xyz += rn * l; + for (i = 0; i < 16; ++i) { + tpos = mat_proj * pos; + tsp = -(tpos.xy / tpos.w) / 2. + 0.5; + tv0 = texture(t0, tsp); + l *= 0.5; + pos.xyz += rn * (step(pos.z, tv0.w) * 2. - 1.) * l; + } + + vec2 ess = abs(tsp - vec2(0.5, 0.5)) - vec2(0.3, 0.3); + ess = clamp(ess, vec2(0, 0), vec2(0.2, 0.2)); + ess = smoothstep(vec2(0.2, 0.2), vec2(0, 0), ess); + coeff *= min(ess.x, ess.y); + float blur = step(0., coeff) * length(pos.xyz - spos.xyz); + vec3 rvs = texture(ts, tsp).rgb; + + qgl_FragData[0] = vec4(rvs.rgb, coeff + clamp(round(blur * 10), 0, 1000)); } diff --git a/qglview/shaders/ssr.vert b/qglview/shaders/ssr.vert index 6bc001e..0e2d5fe 100644 --- a/qglview/shaders/ssr.vert +++ b/qglview/shaders/ssr.vert @@ -1,6 +1,10 @@ #version 150 +in vec3 view_corner; +out vec3 view_dir; + void main(void) { + view_dir = view_corner / view_corner.z; qgl_FragTexture = qgl_Texture; gl_Position = qgl_ftransform(); } diff --git a/qglview/shaders/ssr_blur.frag b/qglview/shaders/ssr_blur.frag new file mode 100644 index 0000000..c23c86d --- /dev/null +++ b/qglview/shaders/ssr_blur.frag @@ -0,0 +1,37 @@ +#version 150 + +uniform sampler2D t0; +uniform float radius = 2; +uniform vec2 dt; + +void main(void) { + vec2 tc = qgl_FragTexture.xy; + float r = float(radius); + vec4 v0 = texture(t0, tc); + float rad; + float coeff = modf(v0.a, rad); + rad /= 10.; + float o = radius * rad, o2 = radius * rad * 2; + vec3 scol = (v0.rgb * 3. + + max(texture(t0, tc + dt * vec2( o, 0 )).rgb, vec3(0)) * 2. + + max(texture(t0, tc + dt * vec2( 0, o )).rgb, vec3(0)) * 2. + + max(texture(t0, tc + dt * vec2( -o, 0 )).rgb, vec3(0)) * 2. + + max(texture(t0, tc + dt * vec2( 0, -o)).rgb, vec3(0)) * 2. + + max(texture(t0, tc + dt * vec2( o, o )).rgb, vec3(0)) * 1.5 + + max(texture(t0, tc + dt * vec2( o, -o)).rgb, vec3(0)) * 1.5 + + max(texture(t0, tc + dt * vec2( -o, -o )).rgb, vec3(0)) * 1.5 + + max(texture(t0, tc + dt * vec2( -o, o )).rgb, vec3(0)) * 1.5 + + max(texture(t0, tc + dt * vec2( o2, 0 )).rgb, vec3(0)) + + max(texture(t0, tc + dt * vec2( 0, o2)).rgb, vec3(0)) + + max(texture(t0, tc + dt * vec2(-o2, 0 )).rgb, vec3(0)) + + max(texture(t0, tc + dt * vec2( 0, -o2)).rgb, vec3(0))/* + + texture(t0, tc + dt * vec2( o2, o )).rgb + + texture(t0, tc + dt * vec2( o2, -o)).rgb + + texture(t0, tc + dt * vec2(-o2, -o )).rgb + + texture(t0, tc + dt * vec2(-o2, o )).rgb + + texture(t0, tc + dt * vec2( o, o2)).rgb + + texture(t0, tc + dt * vec2( o, -o2)).rgb + + texture(t0, tc + dt * vec2( -o, -o2)).rgb + + texture(t0, tc + dt * vec2( -o, o2)).rgb*/) / 21.; + qgl_FragData[0] = vec4(scol, v0.w); +} diff --git a/qglview/shaders/ssr_blur.vert b/qglview/shaders/ssr_blur.vert new file mode 100644 index 0000000..6bc001e --- /dev/null +++ b/qglview/shaders/ssr_blur.vert @@ -0,0 +1,6 @@ +#version 150 + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); +} diff --git a/qglview/shaders/ssr_merge.frag b/qglview/shaders/ssr_merge.frag new file mode 100644 index 0000000..e0120b8 --- /dev/null +++ b/qglview/shaders/ssr_merge.frag @@ -0,0 +1,12 @@ +#version 150 + +uniform sampler2D t0, ts; + +void main(void) { + ivec2 tc = ivec2(gl_FragCoord.xy); + vec4 v0 = texelFetch(t0, tc, 0), vs = texelFetch(ts, tc, 0); + float rad; + float coeff = modf(v0.a, rad); + qgl_FragData[0].rgb = mix(vs.rgb, v0.rgb, coeff); + //qgl_FragData[0].rgb = vec3(v0.rgb); +} diff --git a/qglview/shaders/ssr_merge.vert b/qglview/shaders/ssr_merge.vert new file mode 100644 index 0000000..6bc001e --- /dev/null +++ b/qglview/shaders/ssr_merge.vert @@ -0,0 +1,6 @@ +#version 150 + +void main(void) { + qgl_FragTexture = qgl_Texture; + gl_Position = qgl_ftransform(); +}