diff --git a/CMakeLists.txt b/CMakeLists.txt index f050970..e8c19eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ project(QGLEngine) if (NOT DEFINED SHSTKPROJECT) include(SHSTKQtMacros) endif() +find_package(PIP REQUIRED) find_package(QAD REQUIRED) shstk_qt_founded(QtVersions) set(_qgl_ok 0) @@ -23,7 +24,6 @@ if (NOT _qgl_ok) message(WARNING "Building ${PROJECT_NAME} available only on Qt5/6!") else() include(SHSTKQtMacros) - include_directories("c:/sdk/MinGW/x32/lib/gcc/i686-w64-mingw32/8.1.0/include") set(QGLEngine_MAJOR 1) set(QGLEngine_MINOR 0) diff --git a/shaders/ds_geom.glsl b/shaders/ds_geom.glsl index 617a6ee..42e82c3 100644 --- a/shaders/ds_geom.glsl +++ b/shaders/ds_geom.glsl @@ -6,7 +6,7 @@ out vec4 object_color; void main(void) { qgl_MaterialIndex = qgl_Material; - qgl_FragTexture = qgl_Texture; + qgl_FragTexture = qgl_getFragTexture(); gl_Position = qgl_ftransform(); geom_normal = normalize(qgl_Normal * qgl_getNormalMatrix()); diff --git a/shaders/ds_tonemap.glsl b/shaders/ds_tonemap.glsl index b9b1f8a..6b3aedc 100644 --- a/shaders/ds_tonemap.glsl +++ b/shaders/ds_tonemap.glsl @@ -20,6 +20,6 @@ void main(void) { float g = gamma / frame_max; res /= l; l = 1 - exp(-l*g); - res *= l; + res = max(vec3(0.f), res * l); qgl_FragColor = vec4(res, dot(res, luma)); } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fabb74e..644a085 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -26,7 +26,7 @@ qad_add_library(${PROJECT_NAME} ${QGLEngine_LIB_TYPE} out_CPP ${_RC}) qad_generate_export_header(${PROJECT_NAME}) list(APPEND out_HDR "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_export.h") qad_target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}" ${_includes}) -qad_target_link_libraries(${PROJECT_NAME} QAD::Widgets assimp ${OPENGL_LIBRARIES}) +qad_target_link_libraries(${PROJECT_NAME} QAD::Widgets QAD::PIQtUtils assimp ${OPENGL_LIBRARIES}) message(STATUS "Building QGLEngine version ${QGLEngine_VERSION} (${QGLEngine_LIB_TYPE_MSG}) for ${QtVersions}") list(APPEND QT_MULTILIB_LIST ${PROJECT_NAME}) diff --git a/src/core/core/glframebuffer_mipmap.cpp b/src/core/core/glframebuffer_mipmap.cpp index cb7f291..ffe85c1 100644 --- a/src/core/core/glframebuffer_mipmap.cpp +++ b/src/core/core/glframebuffer_mipmap.cpp @@ -32,6 +32,11 @@ FramebufferMipmap::FramebufferMipmap(const Framebuffer & fb, int index_from_, in FramebufferMipmap::~FramebufferMipmap() {} +void FramebufferMipmap::setIndexFrom(int index) { + index_from = index; +} + + void FramebufferMipmap::resize() { QSize sz = src_fb.size(); for (int i = 0; i < fbo.size(); ++i) { diff --git a/src/core/core/glframebuffer_mipmap.h b/src/core/core/glframebuffer_mipmap.h index 8a5c809..e469491 100644 --- a/src/core/core/glframebuffer_mipmap.h +++ b/src/core/core/glframebuffer_mipmap.h @@ -35,6 +35,7 @@ public: int height(int level) const { return fbo[level]->hei; } QSize size(int level) const { return fbo[level]->size(); } QRect rect(int level) const { return fbo[level]->rect(); } + void setIndexFrom(int index); void resize(); void create(); diff --git a/src/core/core/glframebuffereffectbase.h b/src/core/core/glframebuffereffectbase.h index fe3174f..db89069 100644 --- a/src/core/core/glframebuffereffectbase.h +++ b/src/core/core/glframebuffereffectbase.h @@ -21,6 +21,8 @@ #include "glframebuffer.h" +#include + class QGLENGINE_CORE_EXPORT FramebufferEffectBase { friend class FramebufferMipmap; @@ -31,6 +33,10 @@ public: virtual ~FramebufferEffectBase(); virtual void draw() = 0; + void setEnabled(bool on) { enabled_ = on; } + bool isEnabled() const { return enabled_; } + void setParameter(const QString & name, const QVariant & val) { parameters[name] = val; } + virtual QString name() const = 0; protected: void resize(int width, int height, bool force = false); @@ -51,8 +57,9 @@ protected: static void deleteShader(QOpenGLShaderProgram *& s); private: - bool is_loaded = false; - Renderer * r = nullptr; + bool is_loaded = false, enabled_ = true; + Renderer * r = nullptr; + QHash parameters; GLint wid, hei; }; diff --git a/src/core/core/glmaterial.cpp b/src/core/core/glmaterial.cpp index b38aed2..8bf10e8 100644 --- a/src/core/core/glmaterial.cpp +++ b/src/core/core/glmaterial.cpp @@ -29,6 +29,9 @@ Map::Map() { color_offset = 0.f; bitmap_scale = QPointF(1., 1.); use_bitmap = false; + invert_R = false; + invert_G = false; + invert_B = false; _changed = true; _layer = 0; } diff --git a/src/core/core/glmaterial.h b/src/core/core/glmaterial.h index dd7f80a..27ed4fb 100644 --- a/src/core/core/glmaterial.h +++ b/src/core/core/glmaterial.h @@ -38,6 +38,7 @@ public: float color_amount; float color_offset; bool use_bitmap; + bool invert_R, invert_G, invert_B; bool _changed; int _type, _layer; @@ -75,14 +76,28 @@ public: inline QDataStream & operator<<(QDataStream & s, const Map & m) { ChunkStream cs; - cs.add(1, m.bitmap_path).add(2, m.color_amount).add(3, m.color_offset).add(6, m.bitmap_scale).add(7, m.use_bitmap); + cs.add(1, m.bitmap_path) + .add(2, m.color_amount) + .add(3, m.color_offset) + .add(6, m.bitmap_scale) + .add(7, m.use_bitmap) + .add(8, m.invert_R) + .add(9, m.invert_G) + .add(10, m.invert_B); s << cs.data(); return s; } inline QDataStream & operator>>(QDataStream & s, Map & m) { ChunkStream cs(s); cs.readAll(); - cs.get(1, m.bitmap_path).get(2, m.color_amount).get(3, m.color_offset).get(6, m.bitmap_scale).get(7, m.use_bitmap); + cs.get(1, m.bitmap_path) + .get(2, m.color_amount) + .get(3, m.color_offset) + .get(6, m.bitmap_scale) + .get(7, m.use_bitmap) + .get(8, m.invert_R) + .get(9, m.invert_G) + .get(10, m.invert_B); return s; } diff --git a/src/core/core/glmesh.cpp b/src/core/core/glmesh.cpp index 347d70c..585b7d7 100644 --- a/src/core/core/glmesh.cpp +++ b/src/core/core/glmesh.cpp @@ -312,7 +312,7 @@ void Mesh::transformPoints(const QMatrix4x4 & mat) { void Mesh::flipNormals() { if (vertices_.isEmpty()) return; for (int i = 0; i < triangles_.size(); ++i) - piSwap(triangles_[i].p1, triangles_[i].p2); + piSwap(triangles_[i].p0, triangles_[i].p1); for (int i = 0; i < lines_.size(); ++i) piSwap(lines_[i].p0, lines_[i].p1); int ncnt = normals_.size(); diff --git a/src/core/core/glshaders.cpp b/src/core/core/glshaders.cpp index d870a63..78e249f 100644 --- a/src/core/core/glshaders.cpp +++ b/src/core/core/glshaders.cpp @@ -50,7 +50,7 @@ bool addShader(QOpenGLShaderProgram * prog, content.prepend(defs); content.prepend(qgl_common_head); bool ret = prog->addShaderFromSourceCode(type, content.toLatin1()); - if (!ret) qDebug() << "[QGLEngine] Shader" << file << "Compile error:\n" << prog->log(); + if (!ret) qDebug() << "[QGLEngine] Shader" << file << "Compile error:\n" << prog->log().toLocal8Bit().constData(); content.clear(); return ret; } @@ -110,7 +110,7 @@ bool QGLEngineShaders::loadShadersMulti(QOpenGLShaderProgram *& prog, const QStr } if (!addShader(prog, type, cur_shader, file, add_qgl, defs)) return false; if (!prog->link()) { - qDebug() << "[QGLEngine] Shader" << file << "Link error:\n" << prog->log(); + qDebug() << "[QGLEngine] Shader" << file << "Link error:\n" << prog->log().toLocal8Bit().constData(); return false; } qDebug() << "[QGLEngine] Shader" << file << "ok"; @@ -138,7 +138,7 @@ bool QGLEngineShaders::loadShaders(QOpenGLShaderProgram *& prog, const QStringLi if (!addShader(prog, type, cur_shader, f, add_qgl, defs)) return false; } if (!prog->link()) { - qDebug() << "[QGLEngine] Shader" << files << "Link error:\n" << prog->log(); + qDebug() << "[QGLEngine] Shader" << files << "Link error:\n" << prog->log().toLocal8Bit().constData(); return false; } qDebug() << "[QGLEngine] Shader" << files << "ok"; diff --git a/src/core/core/glshaders_headers.h b/src/core/core/glshaders_headers.h index c225070..3f96a1a 100644 --- a/src/core/core/glshaders_headers.h +++ b/src/core/core/glshaders_headers.h @@ -37,13 +37,15 @@ const char qgl_vertex_head[] = "layout(location = 1 ) in vec3 qgl_Vertex "layout(location = 8 ) in uint qgl_ObjectID ;\n" "layout(location = 9 ) in vec4 qgl_ObjectColor ;\n" "layout(location = 10) in mat4 qgl_ModelMatrix ;\n" + "layout(location = 14) in mat2x3 qgl_TextureMatrix ;\n" "out vec2 qgl_FragTexture;\n" "flat out uint qgl_MaterialIndex;\n" "uniform mat4 qgl_ViewMatrix;\n" "uniform mat4 qgl_ViewProjMatrix;\n" "mat3 qgl_getNormalMatrix() {return inverse(mat3(qgl_ViewMatrix * qgl_ModelMatrix));}\n" "mat3 qgl_getTangentMatrix() {return mat3(qgl_ViewMatrix * qgl_ModelMatrix);}\n" - "vec4 qgl_ftransform() {return qgl_ViewProjMatrix * (qgl_ModelMatrix * vec4(qgl_Vertex, 1));}\n" + "vec2 qgl_getFragTexture() {return (vec3(qgl_Texture, 1.f) * qgl_TextureMatrix).xy;}\n" + "vec4 qgl_ftransform() {return qgl_ViewProjMatrix * (qgl_ModelMatrix * vec4(qgl_Vertex, 1.f));}\n" ""; const char qgl_fragment_head[] = diff --git a/src/core/core/glshaders_types.cpp b/src/core/core/glshaders_types.cpp index 1a3de8a..67914e9 100644 --- a/src/core/core/glshaders_types.cpp +++ b/src/core/core/glshaders_types.cpp @@ -64,9 +64,10 @@ void QGLEngineShaders::prepareDrawObj(QOpenGLExtraFunctions * f) { f->glEnableVertexAttribArray(material_loc); f->glEnableVertexAttribArray(object_id_loc); f->glEnableVertexAttribArray(color_loc); - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) f->glEnableVertexAttribArray(modelmatrix_loc + i); - } + for (int i = 0; i < 2; ++i) + f->glEnableVertexAttribArray(texturematrix_loc + i); GLsizei size = sizeof(Object); f->glVertexAttribIPointer(material_loc, 1, GL_UNSIGNED_INT, size, (const void *)material_offset); @@ -80,13 +81,22 @@ void QGLEngineShaders::prepareDrawObj(QOpenGLExtraFunctions * f) { size, (const void *)(modelmatrix_offset + sizeof(QVector4D) * i)); } + for (int i = 0; i < 2; ++i) { + f->glVertexAttribPointer(texturematrix_loc + i, + 3, + GL_FLOAT, + GL_FALSE, + size, + (const void *)(texturematrix_offset + sizeof(QVector3D) * i)); + } f->glVertexAttribDivisor(material_loc, 1); f->glVertexAttribDivisor(object_id_loc, 1); f->glVertexAttribDivisor(color_loc, 1); - for (int i = 0; i < 4; ++i) { + for (int i = 0; i < 4; ++i) f->glVertexAttribDivisor(modelmatrix_loc + i, 1); - } + for (int i = 0; i < 2; ++i) + f->glVertexAttribDivisor(texturematrix_loc + i, 1); } diff --git a/src/core/core/glshaders_types.h b/src/core/core/glshaders_types.h index 4bec346..bc2e36f 100644 --- a/src/core/core/glshaders_types.h +++ b/src/core/core/glshaders_types.h @@ -27,32 +27,34 @@ namespace QGLEngineShaders { /// VBO // geometry -const GLsizei pos_offset = 0; -const GLsizei normal_offset = sizeof(QVector3D) + pos_offset; -const GLsizei tangent_offset = sizeof(QVector3D) + normal_offset; -const GLsizei bitangent_offset = sizeof(QVector3D) + tangent_offset; -const GLsizei tex_offset = sizeof(QVector3D) + bitangent_offset; +const GLsizei pos_offset = 0; +const GLsizei normal_offset = sizeof(QVector3D) + pos_offset; +const GLsizei tangent_offset = sizeof(QVector3D) + normal_offset; +const GLsizei bitangent_offset = sizeof(QVector3D) + tangent_offset; +const GLsizei tex_offset = sizeof(QVector3D) + bitangent_offset; // object -const GLsizei material_offset = 0; -const GLsizei object_id_offset = sizeof(GLuint) + material_offset; -const GLsizei color_offset = sizeof(GLuint) + object_id_offset; -const GLsizei modelmatrix_offset = sizeof(QVector4D) + color_offset; +const GLsizei material_offset = 0; +const GLsizei object_id_offset = sizeof(GLuint) + material_offset; +const GLsizei color_offset = sizeof(GLuint) + object_id_offset; +const GLsizei modelmatrix_offset = sizeof(QVector4D) + color_offset; +const GLsizei texturematrix_offset = sizeof(QVector4D) * 4 + modelmatrix_offset; -const GLsizei is_selected_offset = 0; +const GLsizei is_selected_offset = 0; -const GLuint pos_loc = 1; // qgl_Vertex -const GLuint normal_loc = 2; // qgl_Normal -const GLuint tangent_loc = 3; // qgl_Tangent -const GLuint bitangent_loc = 4; // qgl_Bitangent -const GLuint tex_loc = 5; // qgl_Texture +const GLuint pos_loc = 1; // qgl_Vertex +const GLuint normal_loc = 2; // qgl_Normal +const GLuint tangent_loc = 3; // qgl_Tangent +const GLuint bitangent_loc = 4; // qgl_Bitangent +const GLuint tex_loc = 5; // qgl_Texture -const GLuint material_loc = 6; // qgl_Material -const GLuint object_id_loc = 8; // qgl_ObjectID -const GLuint color_loc = 9; // qgl_ObjectColor -const GLuint modelmatrix_loc = 10; // qgl_ModelViewProjectionMatrix +const GLuint material_loc = 6; // qgl_Material +const GLuint object_id_loc = 8; // qgl_ObjectID +const GLuint color_loc = 9; // qgl_ObjectColor +const GLuint modelmatrix_loc = 10; // qgl_ModelViewProjectionMatrix +const GLuint texturematrix_loc = 14; // qgl_TextureMatrix -const GLuint is_selected_loc = 7; // qgl_ObjectSelected +const GLuint is_selected_loc = 7; // qgl_ObjectSelected #pragma pack(push, 1) struct Vertex { @@ -67,11 +69,13 @@ struct Object { material = object_id = 0; color = QVector4D(1, 1, 1, 1); QMatrix4x4().copyDataTo(modelmatrix); + QMatrix2x3().transposed().copyDataTo(texturematrix); } GLuint material; GLuint object_id; QVector4D color; GLfloat modelmatrix[16]; + GLfloat texturematrix[6]; }; #pragma pack(pop) diff --git a/src/core/core/gltypes.h b/src/core/core/gltypes.h index 5c52cc4..f11cb1f 100644 --- a/src/core/core/gltypes.h +++ b/src/core/core/gltypes.h @@ -77,6 +77,7 @@ # include # include #endif +#include "pimathbase.h" #include "qglengine_core_export.h" #include "qglengine_version.h" diff --git a/src/core/core/measurer.cpp b/src/core/core/measurer.cpp new file mode 100644 index 0000000..4e0ca46 --- /dev/null +++ b/src/core/core/measurer.cpp @@ -0,0 +1,39 @@ +/* + Time mesurer + 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 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 . +*/ + +#include "measurer.h" + +#include + + +Measurer::Measurer(QString * output): out(output) {} + + +Measurer::~Measurer() {} + + +void Measurer::begin(const QString & name) { + n = name; + et.reset(); +} + +void Measurer::end() { + auto ms = et.elapsed_m(); + QTextStream ts(out); + ts << n << ": " << QString::number(ms, 'f', 2) << " ms\n"; +} diff --git a/src/core/core/measurer.h b/src/core/core/measurer.h new file mode 100644 index 0000000..5bc8a32 --- /dev/null +++ b/src/core/core/measurer.h @@ -0,0 +1,44 @@ +/* + Time mesurer + 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 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 . +*/ + +#ifndef measurer_H +#define measurer_H + +#include "qglengine_core_export.h" + +#include +#include + + +class QGLENGINE_CORE_EXPORT Measurer { + friend class ObjectBase; + +public: + Measurer(QString * output); + ~Measurer(); + + void begin(const QString & name); + void end(); + +private: + PITimeMeasurer et; + QString n, *out; +}; + + +#endif diff --git a/src/core/render/gltexture_manager.cpp b/src/core/render/gltexture_manager.cpp index 781ca3f..ef08b69 100644 --- a/src/core/render/gltexture_manager.cpp +++ b/src/core/render/gltexture_manager.cpp @@ -28,6 +28,10 @@ QVector3D colorVector(QRgb c) { } +void TextureManager::addSearchPath(const QString & path) { + if (!search_pathes.contains(path)) search_pathes << path; +} + QString TextureManager::findFile(const QString & path) { return ::findFile(path, search_pathes); } @@ -38,7 +42,7 @@ GLuint TextureManager::loadTexture(const QString & path, bool ownership, bool bu if (p.isEmpty()) return 0; int tid = textureID(p, bump); if (tid > 0) { - // qDebug() << "[TextureManager] Found" << path << "as" << tid; + qDebug() << "[TextureManager] Found" << path << "as" << tid; return tid; } QImage image(p); @@ -70,7 +74,7 @@ GLuint TextureManager::loadTexture(const QImage & im, bool ownership, bool bump) qDebug() << "[TextureManager] Can`t load image"; return tid; } - // qDebug() << "[TextureManager] Loaded image as" << tid; + qDebug() << "[TextureManager] Loaded image as" << tid; return tid; } diff --git a/src/core/render/gltexture_manager.h b/src/core/render/gltexture_manager.h index bfc0e08..08afc52 100644 --- a/src/core/render/gltexture_manager.h +++ b/src/core/render/gltexture_manager.h @@ -34,9 +34,7 @@ public: virtual ~TextureManager() {} static void addSearchPath(const QString & path) { - if (!search_pathes.contains(path)) search_pathes << path; - } - static void clearSearchPathes() { search_pathes.clear(); } + if (!search_pathes; { search_pathes.clear(); } static QStringList searchPathes() { return search_pathes; } static QString findFile(const QString & path); GLuint loadTexture(const QString & path, bool ownership = true, bool bump = false); diff --git a/src/core/render/renderer.cpp b/src/core/render/renderer.cpp index 4e2ee12..cc4d3f9 100644 --- a/src/core/render/renderer.cpp +++ b/src/core/render/renderer.cpp @@ -160,16 +160,12 @@ void Renderer::initShaders() { if (!need_init_shaders) return; need_init_shaders = false; initUniformBuffer(shaders.value(srGeometryPass), &buffer_materials, bpMaterials, "QGLMaterialData"); - initUniformBuffer(shaders.value(srLightOmniPass), &buffer_materials, bpMaterials, "QGLMaterialData"); - initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights, bpLightParameters, "QGLLightParameterData"); - initUniformBuffer(shaders.value(srLightOmniPass), &buffer_lights_pos, bpLightPositions, "QGLLightPositionData"); - initUniformBuffer(shaders.value(srLightSpotPass), &buffer_materials, bpMaterials, "QGLMaterialData"); - initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights, bpLightParameters, "QGLLightParameterData"); - initUniformBuffer(shaders.value(srLightSpotPass), &buffer_lights_pos, bpLightPositions, "QGLLightPositionData"); - ShaderRole roles[] = {srLightOmniPass, srLightSpotPass}; QOpenGLShaderProgram * prog = 0; - for (int p = 0; p < 2; ++p) { - if (!bindShader(roles[p], &prog)) continue; + for (ShaderRole role: {srLightOmniPass, srLightSpotPass}) { + initUniformBuffer(shaders.value(role), &buffer_materials, bpMaterials, "QGLMaterialData"); + initUniformBuffer(shaders.value(role), &buffer_lights, bpLightParameters, "QGLLightParameterData"); + initUniformBuffer(shaders.value(role), &buffer_lights_pos, bpLightPositions, "QGLLightPositionData"); + if (!bindShader(role, &prog)) continue; for (int i = 0; i < 5; ++i) prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i); prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount); @@ -232,7 +228,8 @@ void Renderer::fillObjectsBuffer(const ObjectBaseList & ol, RenderPass pass) { } so.object_id = o->id(); o->worldTransform().transposed().copyDataTo(so.modelmatrix); - // qDebug() << "load obj" << o->name() << o->worldTransform(); + o->textureGLMatrix().copyDataTo(so.texturematrix); + // qDebug() << "load obj" << o->name() << o->textureMatrix() << tmat; } // qDebug() << "fillObjectsBuffer" << ol.size(); } @@ -300,6 +297,10 @@ void Renderer::renderLight(int first_wr_buff, bool clear_only) { void Renderer::renderScene() { + timings.clear(); + Measurer phase(&timings); + + phase.begin("init"); initShaders(); tex_env.load(); QOpenGLExtraFunctions * f = view; @@ -308,21 +309,27 @@ void Renderer::renderScene() { QOpenGLShaderProgram * prog = 0; bool scene_changed = scene.prepare(); scene.destroyUnused(f); + phase.end(); /// reload materials on change + phase.begin("scene reload"); if (scene_changed || scene.need_reload_materials) { rend_selection.generateObjectsID(scene); reloadMaterials(scene); if (edit_mode) recreateMaterialThumbnails(); emit view->materialsChanged(); } + phase.end(); /// material thumbnails + phase.begin("materials"); if (edit_mode && !scene_changed) { rend_mat.procQueue(); } + phase.end(); /// lights + phase.begin("lights prepare"); cur_lights = scene.lights_used; bool use_camlight = (camera_light_mode == QGLView::clmOn); if ((camera_light_mode == QGLView::clmAuto) && cur_lights.isEmpty()) { @@ -337,13 +344,17 @@ void Renderer::renderScene() { reloadLightsParameters(cur_lights); } reloadLightsPositions(cam); + phase.end(); /// selection + phase.begin("selection"); if (edit_mode) { rend_selection.renderSelection(scene); } + phase.end(); /// solid geometry pass + phase.begin("geometry solid"); fbo_ds.bind(); glEnableDepth(); glClearFramebuffer(); @@ -356,11 +367,15 @@ void Renderer::renderScene() { fbo_ds.blit(dbrNormalZ, fbo_ds.id(), dbrNormalZSolid, fbo_ds.rect(), fbo_ds.rect()); fbo_ds.blit(dbrSpecularReflect, fbo_ds.id(), dbrSpecularReflectSolid, fbo_ds.rect(), fbo_ds.rect()); fbo_ds.release(); + phase.end(); /// lighting passes + phase.begin("... light"); renderLight(obrSolidOmni, scene.geometries_used[rpSolid].isEmpty()); + phase.end(); /// transparent geometry pass + phase.begin("geometry trans"); fbo_ds.bind(); glEnableDepth(); fbo_ds.setWriteBuffers({0, 1, 2, 3, 4}); @@ -370,11 +385,15 @@ void Renderer::renderScene() { renderObjects(scene, rpTransparent); } fbo_ds.release(); + phase.end(); /// lighting passes + phase.begin("... light"); renderLight(obrTransparentOmni, scene.geometries_used[rpTransparent].isEmpty()); + phase.end(); /// blending layers + phase.begin("blending"); if (bindShader(srFinalPass, &prog)) { fbo_out.bindColorTexture(obrSolidOmni, 1); fbo_out.bindColorTexture(obrSolidSpot, 2); @@ -383,10 +402,12 @@ void Renderer::renderScene() { fbo_out.setWriteBuffer(obrGeneral0); renderQuad(prog, quad); } + phase.end(); cur_write_plane = obrGeneral0; /// tonemapping + phase.begin("tonemap"); tone_proc.process(); auto free = getFreePlanes(0); if (bindShader(srTonemapPass, &prog)) { @@ -398,8 +419,10 @@ void Renderer::renderScene() { } else { fbo_out.blit(prev_write_plane, fbo_out.id(), cur_write_plane, fbo_out.rect(), fbo_out.rect()); } + phase.end(); /// FXAA + phase.begin("fxaa"); if (view->isFeatureEnabled(QGLView::qglFXAA)) { prog = shader_fxaa; if (bindShader(prog)) { @@ -409,27 +432,37 @@ void Renderer::renderScene() { renderQuad(prog, quad, 0, false); } } + phase.end(); /// custom effects for (auto * e: fb_effects) { + if (!e->isEnabled()) continue; + phase.begin("fb effect " + e->name()); e->reloadShadersInternal(); e->drawInternal(); + phase.end(); } fbo_out.release(); /// apply hovers and selection frame + phase.begin("service"); if (edit_mode) { rend_selection.drawSelection(fbo_out, cur_write_plane); rend_service.renderService(); } else { fbo_out.blit(cur_write_plane, 0, 0, fbo_out.rect(), QRect(QPoint(), view->size())); } + phase.end(); + + /// grab framebuffer + phase.begin("grab"); if (is_grabbing) { fbo_out.queryImage(0); last_img = fbo_out.getImage().mirrored(); // qDebug() << last_img.size(); } + phase.end(); } diff --git a/src/core/render/renderer.h b/src/core/render/renderer.h index 2b76175..c54c370 100644 --- a/src/core/render/renderer.h +++ b/src/core/render/renderer.h @@ -99,6 +99,7 @@ public: QImage getImage() const { return last_img; } void addFramebufferEffect(FramebufferEffectBase * e); void clearFramebufferEffects() { fb_effects.clear(); } + QString getTimings() const { return timings; } QImage materialThumbnail(Material * m) { return rend_mat.materialThumbnail(m); } void recreateMaterialThumbnails(bool force_all = false) { rend_mat.recreateMaterialThumbnails(force_all); } @@ -144,6 +145,7 @@ private: QMap> cur_lights; QVector fb_effects; QImage last_img; + QString timings; bool is_grabbing = false; }; diff --git a/src/core/render/renderer_base.h b/src/core/render/renderer_base.h index 8813af0..cfb297a 100644 --- a/src/core/render/renderer_base.h +++ b/src/core/render/renderer_base.h @@ -22,6 +22,7 @@ #include "glbuffer.h" #include "glshaders_types.h" #include "gltexturearray.h" +#include "measurer.h" class QGLENGINE_CORE_EXPORT RendererBase { diff --git a/src/core/render/tonemapping_proc.cpp b/src/core/render/tonemapping_proc.cpp index 3cf21de..d8a67b8 100644 --- a/src/core/render/tonemapping_proc.cpp +++ b/src/core/render/tonemapping_proc.cpp @@ -31,7 +31,7 @@ TonemappingProc::TonemappingProc(Renderer * rend) : QThread() , r(rend) , fbo_1x1(r->view, 1, false, GL_RGB32F) - , fbomm(r->fbo_out, Renderer::obrGeneral1, 3) + , fbomm(r->fbo_out, Renderer::obrGeneral0, 3) , buffer_vbo(GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW) { shader_sum = 0; timer_delim = 0; diff --git a/src/core/scene/globject.cpp b/src/core/scene/globject.cpp index 48639f6..34b5938 100644 --- a/src/core/scene/globject.cpp +++ b/src/core/scene/globject.cpp @@ -63,27 +63,28 @@ ObjectBase::~ObjectBase() { ObjectBase * ObjectBase::clone(bool withChildren) { - ObjectBase * o = new ObjectBase(); - o->prev_pass = prev_pass; - o->is_init = false; - o->accept_light = accept_light; - o->accept_fog = accept_fog; - o->visible_ = visible_; - o->color_ = color_; - o->type_ = type_; - o->raw_matrix = raw_matrix; - o->mat_ = mat_; - o->trans = trans; - o->itransform_ = itransform_; - o->bound = bound; - o->name_ = name_; // + "_copy"; - o->blend_src = blend_src; - o->blend_dest = blend_dest; - o->pos_h = pos_h; - o->material_ = material_; - o->mesh_ = mesh_; - o->meta = meta; - o->scene_ = nullptr; + ObjectBase * o = new ObjectBase(); + o->prev_pass = prev_pass; + o->is_init = false; + o->accept_light = accept_light; + o->accept_fog = accept_fog; + o->visible_ = visible_; + o->color_ = color_; + o->type_ = type_; + o->raw_matrix = raw_matrix; + o->mat_ = mat_; + o->trans = trans; + o->trans_texture = trans_texture; + o->itransform_ = itransform_; + o->bound = bound; + o->name_ = name_; // + "_copy"; + o->blend_src = blend_src; + o->blend_dest = blend_dest; + o->pos_h = pos_h; + o->material_ = material_; + o->mesh_ = mesh_; + o->meta = meta; + o->scene_ = nullptr; if (withChildren) { for (int i = 0; i < children_.size(); ++i) o->addChild(children_[i]->clone(withChildren)); @@ -345,6 +346,31 @@ void ObjectBase::cleanTree() { } +void ObjectBase::setTextureTransform(const Transform & t) { + trans_texture = t; + setObjectsChanged(); +} + + +void ObjectBase::setTextureMatrix(const QMatrix4x4 & t) { + trans_texture.setMatrix(t); + setObjectsChanged(); +} + + +QMatrix4x4 ObjectBase::textureMatrix() const { + return trans_texture.matrix(); +} + + +QGenericMatrix<3, 2, float> ObjectBase::textureGLMatrix() const { + QGenericMatrix<3, 2, float> ret = textureMatrix().toGenericMatrix<3, 2>(); + ret(0, 2) = -trans_texture.translation().x(); + ret(1, 2) = -trans_texture.translation().y(); + return ret; +} + + bool ObjectBase::isSelected(bool check_parents) const { if (!check_parents) return selected_; if (selected_) return true; @@ -600,6 +626,7 @@ ObjectBase * Light::clone(bool withChildren) { o->color_ = color_; o->light_type = light_type; o->trans = trans; + o->trans_texture = trans_texture; o->aim_dist = aim_dist; o->angle_start = angle_start; o->angle_end = angle_end; @@ -634,7 +661,8 @@ QDataStream & operator<<(QDataStream & s, const ObjectBase * p) { .add(17, p->name_) .add(18, p->meta) .add(19, p->color_) - .add(20, p->trans); + .add(20, p->trans) + .add(21, p->trans_texture); // qDebug() << "place self done"; if (p->type_ == ObjectBase::glLight) { // qDebug() << "place light ..."; @@ -734,6 +762,9 @@ QDataStream & operator>>(QDataStream & s, ObjectBase *& p) { case 20: if (p) p->trans = cs.getData(); break; + case 21: + if (p) p->trans_texture = cs.getData(); + break; case 100: if (l) l->setAim(cs.getData()); break; diff --git a/src/core/scene/globject.h b/src/core/scene/globject.h index 68ec99b..9a36608 100644 --- a/src/core/scene/globject.h +++ b/src/core/scene/globject.h @@ -267,11 +267,18 @@ public: void setTransform(const Transform & t); void setMatrix(const QMatrix4x4 & t); QMatrix4x4 matrix() const; + bool isRawMatrix() { return raw_matrix; } QVector3D inParentSpace(const QVector3D & v) const; void transferTransformToChildren(bool only_scale = false); void cleanTree(); + Transform textureTransform() { return trans_texture; } + void setTextureTransform(const Transform & t); + void setTextureMatrix(const QMatrix4x4 & t); + QMatrix4x4 textureMatrix() const; + QGenericMatrix<3, 2, float> textureGLMatrix() const; + bool isAcceptLight() const { return accept_light; } void setAcceptLight(bool yes) { accept_light = yes; } @@ -333,7 +340,7 @@ protected: Type type_; RenderMode render_mode; Box3D bound; - Transform trans; + Transform trans, trans_texture; ObjectBaseList children_; QMatrix4x4 itransform_, mat_; QString name_; diff --git a/src/icons/legend.png b/src/icons/legend.png new file mode 100644 index 0000000..94447c2 Binary files /dev/null and b/src/icons/legend.png differ diff --git a/src/qglview_test/qglview_window.cpp b/src/qglview_test/qglview_window.cpp index 2eab5d1..d519913 100644 --- a/src/qglview_test/qglview_window.cpp +++ b/src/qglview_test/qglview_window.cpp @@ -31,6 +31,7 @@ class Effect1: public FramebufferEffectBase { public: + QString name() const { return "Blur"; } void reloadShaders() { QGLEngineShaders::loadShadersMulti(mys, "test1.glsl"); } void draw() { auto planes = getFreePlanes(1); @@ -98,6 +99,7 @@ QGLViewWindow::QGLViewWindow(QWidget * parent): QMainWindow(parent), Ui::QGLView startTimer(1000 / 60); connect(view->view(), SIGNAL(keyEvent(Qt::Key, Qt::KeyboardModifiers)), this, SLOT(view_keyEvent(Qt::Key, Qt::KeyboardModifiers))); + connect(view->view(), &QGLView::glEndPaint, this, [this]() { labelTimings->setText(view->view()->renderer_.getTimings()); }); // connect(matEditor, SIGNAL(changed()), this, SLOT(materialChanged())); sceneTree->assignQGLView(view->view()); matEditor->assignQGLView(view->view()); @@ -206,7 +208,7 @@ void QGLViewWindow::on_actionSaveSelected_triggered() { if (f.right(4).toLower() != ".qgl") f += ".qgl"; prev_path = f; QApplication::setOverrideCursor(Qt::WaitCursor); - /// saveToQGLFile(f, sel_obj); + // saveToQGLFile(f, sel_obj); QApplication::restoreOverrideCursor(); } diff --git a/src/qglview_test/qglview_window.ui b/src/qglview_test/qglview_window.ui index cb41efd..78a5f3b 100644 --- a/src/qglview_test/qglview_window.ui +++ b/src/qglview_test/qglview_window.ui @@ -80,7 +80,7 @@ 0 0 - 904 + 881 840 @@ -723,6 +723,13 @@ + + + + TextLabel + + + diff --git a/src/widgets/material_map_editor.cpp b/src/widgets/material_map_editor.cpp index 5526b4b..5914fc2 100644 --- a/src/widgets/material_map_editor.cpp +++ b/src/widgets/material_map_editor.cpp @@ -28,6 +28,7 @@ MaterialMapEditor::MaterialMapEditor(QWidget * parent): QWidget(parent) { ui = new Ui::MaterialMapEditor(); ui->setupUi(this); + ui->buttonChannels->addActions({ui->actionInvert_R, ui->actionInvert_G, ui->actionInvert_B}); ui->widgetMap->hide(); active = true; } @@ -67,7 +68,10 @@ void MaterialMapEditor::mapChanged() { } map->bitmap_scale.setX(ui->spinScaleX->value()); map->bitmap_scale.setY(ui->spinScaleY->value()); - active = true; + map->invert_R = ui->actionInvert_R->isChecked(); + map->invert_G = ui->actionInvert_G->isChecked(); + map->invert_B = ui->actionInvert_B->isChecked(); + active = true; emit changed(); } @@ -86,6 +90,9 @@ void MaterialMapEditor::setMap(Map * m) { ui->spinScaleY->setValue(map->bitmap_scale.y()); ui->linePath->setProperty("GLpath", map->bitmap_path); ui->linePath->setText(QFileInfo(map->bitmap_path).fileName()); + ui->actionInvert_R->setChecked(map->invert_R); + ui->actionInvert_G->setChecked(map->invert_G); + ui->actionInvert_B->setChecked(map->invert_B); updateIcon(); active = true; } @@ -152,3 +159,18 @@ void MaterialMapEditor::on_checkMap_toggled(bool checked) { ui->stackedWidget->setCurrentIndex(checked ? 1 : 0); mapChanged(); } + + +void MaterialMapEditor::on_actionInvert_R_toggled(bool checked) { + mapChanged(); +} + + +void MaterialMapEditor::on_actionInvert_G_toggled(bool checked) { + mapChanged(); +} + + +void MaterialMapEditor::on_actionInvert_B_toggled(bool checked) { + mapChanged(); +} diff --git a/src/widgets/material_map_editor.h b/src/widgets/material_map_editor.h index a06f130..0ec3b56 100644 --- a/src/widgets/material_map_editor.h +++ b/src/widgets/material_map_editor.h @@ -52,6 +52,9 @@ private slots: void on_buttonSelect_clicked(); void on_buttonClear_clicked(); void on_checkMap_toggled(bool checked); + void on_actionInvert_R_toggled(bool checked); + void on_actionInvert_G_toggled(bool checked); + void on_actionInvert_B_toggled(bool checked); signals: void changed(); diff --git a/src/widgets/material_map_editor.ui b/src/widgets/material_map_editor.ui index 33ca383..b5d887c 100644 --- a/src/widgets/material_map_editor.ui +++ b/src/widgets/material_map_editor.ui @@ -156,7 +156,7 @@ - + :/icons/edit-delete.png:/icons/edit-delete.png @@ -164,11 +164,22 @@ - + :/icons/document-open.png:/icons/document-open.png + + + + + :/icons/legend.png:/icons/legend.png + + + QToolButton::InstantPopup + + + @@ -332,6 +343,36 @@ + + + true + + + Invert R + + + + + true + + + Invert G + + + Invert G + + + + + true + + + Invert B + + + Invert B + + @@ -351,8 +392,8 @@ - - + + diff --git a/src/widgets/materials_editor.ui b/src/widgets/materials_editor.ui index e416569..8fc246a 100644 --- a/src/widgets/materials_editor.ui +++ b/src/widgets/materials_editor.ui @@ -90,7 +90,7 @@ Unset - + :/icons/dialog-cancel.png:/icons/dialog-cancel.png @@ -101,7 +101,7 @@ Assign - + :/icons/go-jump.png:/icons/go-jump.png @@ -112,7 +112,7 @@ Add - + :/icons/list-add.png:/icons/list-add.png @@ -123,7 +123,7 @@ Delete - + :/icons/edit-delete.png:/icons/edit-delete.png @@ -134,7 +134,7 @@ Rename ... - + :/icons/edit-rename.png:/icons/edit-rename.png @@ -145,7 +145,7 @@ Clone - + :/icons/edit-copy.png:/icons/edit-copy.png @@ -187,7 +187,7 @@ 0 0 386 - 440 + 418 @@ -239,10 +239,9 @@ - - + + - diff --git a/src/widgets/object_editor.cpp b/src/widgets/object_editor.cpp index 3bc4b23..41ee4f7 100644 --- a/src/widgets/object_editor.cpp +++ b/src/widgets/object_editor.cpp @@ -42,6 +42,11 @@ ObjectEditor::ObjectEditor(QWidget * parent): QWidget(parent) { foreach(QObject * o, ol) connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinChanged(double))); + ol.clear(); + ol << ui->spinRotationTexture << ui->spinOffsetTextureX << ui->spinOffsetTextureY << ui->spinScaleTextureX << ui->spinScaleTextureY; + foreach(QObject * o, ol) + connect(o, SIGNAL(valueChanged(double)), this, SLOT(spinTextureChanged(double))); + ol.clear(); ol << ui->spinLightIntensity << ui->spinLightDecayConst << ui->spinLightDecayLinear << ui->spinLightDecayQuadratic << ui->spinLightAngleStart << ui->spinLightAngleEnd << ui->spinAimDist; @@ -117,6 +122,13 @@ void ObjectEditor::setObject(ObjectBase * o) { ui->spinScaleX->setValue(o->scaleX()); ui->spinScaleY->setValue(o->scaleY()); ui->spinScaleZ->setValue(o->scaleZ()); + + ui->spinRotationTexture->setValue(o->textureTransform().rotationZ()); + ui->spinOffsetTextureX->setValue(o->textureTransform().translation().x()); + ui->spinOffsetTextureY->setValue(o->textureTransform().translation().y()); + ui->spinScaleTextureX->setValue(o->textureTransform().scale3D().x()); + ui->spinScaleTextureY->setValue(o->textureTransform().scale3D().y()); + ui->checkVisible->setChecked(o->isVisible()); ui->checkAcceptLight->setChecked(o->isAcceptLight()); ui->checkAcceptFog->setChecked(o->isAcceptFog()); @@ -210,6 +222,23 @@ void ObjectEditor::spinChanged(double v) { } +void ObjectEditor::spinTextureChanged(double v) { + if (!view || !active) return; + ObjectBaseList sol = view->selectedObjects(true); + QObject * s = sender(); + foreach(ObjectBase * o, sol) { + auto ttr = o->textureTransform(); + if (s == ui->spinRotationTexture) ttr.setRotationZ(v); + if (s == ui->spinOffsetTextureX) ttr.setTranslationX(v); + if (s == ui->spinOffsetTextureY) ttr.setTranslationY(v); + if (s == ui->spinScaleTextureX) ttr.setScaleX(v); + if (s == ui->spinScaleTextureY) ttr.setScaleY(v); + o->setTextureTransform(ttr); + } + ignore_next = true; +} + + void ObjectEditor::spinLightChanged(double v) { if (!view || !active) return; QList sll = view->selectedLights(); diff --git a/src/widgets/object_editor.h b/src/widgets/object_editor.h index 47b9ef7..8e3d5a5 100644 --- a/src/widgets/object_editor.h +++ b/src/widgets/object_editor.h @@ -51,6 +51,7 @@ private slots: void on_comboLightType_currentIndexChanged(int index); void on_buttonColor_colorChanged(const QColor & v); void spinChanged(double v); + void spinTextureChanged(double v); void spinLightChanged(double v); void spinCameraChanged(double v); void checkChanged(bool v); diff --git a/src/widgets/object_editor.ui b/src/widgets/object_editor.ui index 58ec410..c7de5a2 100644 --- a/src/widgets/object_editor.ui +++ b/src/widgets/object_editor.ui @@ -7,7 +7,7 @@ 0 0 466 - 778 + 915 @@ -297,26 +297,134 @@ + + + + Texture + + + + + + + + + + 0 + 0 + + + + SX: + + + + + + + 1.000000000000000 + + + + + + + + + + + 0 + 0 + + + + X: + + + + + + + + 0 + 0 + + + + Y: + + + + + + + + 0 + 0 + + + + R: + + + + + + + 1.000000000000000 + + + + + + + -360.000000000000000 + + + 360.000000000000000 + + + 1 + + + 4.500000000000000 + + + 90.000000000000000 + + + ° + + + QSlider::TicksAbove + + + 90 + + + + + + + + 0 + 0 + + + + SY: + + + + + + - - + + - Accept fog - - - - - - - Accept light - - - - - - - Visible + Receive shadows @@ -327,10 +435,24 @@ - - + + - Receive shadows + Accept fog + + + + + + + Visible + + + + + + + Accept light diff --git a/src/widgets/primitiveeditor.ui b/src/widgets/primitiveeditor.ui index 9238a84..c5c286c 100644 --- a/src/widgets/primitiveeditor.ui +++ b/src/widgets/primitiveeditor.ui @@ -379,7 +379,7 @@ Add - + :/icons/list-add.png:/icons/list-add.png @@ -411,7 +411,7 @@ - + diff --git a/src/widgets/scene_tree.ui b/src/widgets/scene_tree.ui index e0c943c..162aba3 100644 --- a/src/widgets/scene_tree.ui +++ b/src/widgets/scene_tree.ui @@ -38,7 +38,7 @@ - + :/icons/configure.png:/icons/configure.png @@ -59,7 +59,7 @@ Expand tree - + :/icons/expand.png:/icons/expand.png @@ -70,7 +70,7 @@ Collapse tree - + :/icons/collapse.png:/icons/collapse.png @@ -127,7 +127,7 @@ - + :/icons/type-camera.png:/icons/type-camera.png @@ -136,7 +136,7 @@ - + :/icons/edit-delete.png:/icons/edit-delete.png @@ -145,7 +145,7 @@ - + :/icons/edit-copy.png:/icons/edit-copy.png @@ -163,7 +163,7 @@ - + :/icons/go-top.png:/icons/go-top.png @@ -172,7 +172,7 @@ - + :/icons/type-geo.png:/icons/type-geo.png @@ -181,7 +181,7 @@ - + :/icons/format-fill-color.png:/icons/format-fill-color.png @@ -190,7 +190,7 @@ - + :/icons/add-type-empty.png:/icons/add-type-empty.png @@ -199,7 +199,7 @@ - + :/icons/add-type-light.png:/icons/add-type-light.png @@ -208,7 +208,7 @@ - + :/icons/add-type-camera.png:/icons/add-type-camera.png @@ -220,7 +220,7 @@ true - + :/icons/type-empty.png:/icons/type-empty.png @@ -232,7 +232,7 @@ true - + :/icons/type-geo.png:/icons/type-geo.png @@ -244,7 +244,7 @@ true - + :/icons/type-light.png:/icons/type-light.png @@ -256,7 +256,7 @@ true - + :/icons/type-camera.png:/icons/type-camera.png @@ -270,7 +270,7 @@ - + :/icons/type-camera.png:/icons/type-camera.png @@ -279,7 +279,7 @@ - + :/icons/type-camera.png:/icons/type-camera.png @@ -300,15 +300,7 @@ - - - - - - - - - + diff --git a/src/widgets/view_editor.ui b/src/widgets/view_editor.ui index df6e181..96b537a 100644 --- a/src/widgets/view_editor.ui +++ b/src/widgets/view_editor.ui @@ -506,7 +506,7 @@ - + diff --git a/src/widgets/widgets.qrc b/src/widgets/widgets.qrc index c83819f..86c45f5 100644 --- a/src/widgets/widgets.qrc +++ b/src/widgets/widgets.qrc @@ -13,6 +13,7 @@ ../icons/edit-paste.png ../icons/document-edit.png ../icons/group.png + ../icons/legend.png ../icons/format-fill-color.png