From e7f71b801b82f84d175c2fe0070900c44f0484a5 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Tue, 9 Apr 2024 17:54:19 +0300 Subject: [PATCH 1/6] Instancing refactoring --- engine/includes/commandbuffer.h | 4 +- engine/src/commandbuffer.cpp | 12 ++--- engine/src/components/particlerender.cpp | 8 +-- engine/src/components/spriterender.cpp | 4 +- .../editor/shadertools/shaders/ShaderLayout.h | 19 ++++--- .../editor/shadertools/shaders/Skinned.vert | 4 -- .../editor/shadertools/shaders/Static.vert | 11 +--- .../rendergl/includes/commandbuffergl.h | 4 +- .../rendergl/includes/resources/meshgl.h | 5 +- .../renders/rendergl/src/commandbuffergl.cpp | 54 ++++--------------- .../renders/rendergl/src/resources/meshgl.cpp | 23 +------- 11 files changed, 43 insertions(+), 105 deletions(-) diff --git a/engine/includes/commandbuffer.h b/engine/includes/commandbuffer.h index 2cfea408b..a497dfe5b 100644 --- a/engine/includes/commandbuffer.h +++ b/engine/includes/commandbuffer.h @@ -64,9 +64,9 @@ class ENGINE_EXPORT CommandBuffer: public Object { virtual void dispatchCompute(ComputeInstance *shader, int32_t groupsX, int32_t groupsY, int32_t groupsZ); - virtual void drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *material = nullptr); + virtual void drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *instance = nullptr); - virtual void drawMeshInstanced(const Matrix4 *transform, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *material = nullptr); + virtual void drawMeshInstanced(const Matrix4 *transform, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *instance = nullptr); virtual void setRenderTarget(RenderTarget *target, uint32_t level = 0); diff --git a/engine/src/commandbuffer.cpp b/engine/src/commandbuffer.cpp index f1fba4d8f..b3f818f50 100644 --- a/engine/src/commandbuffer.cpp +++ b/engine/src/commandbuffer.cpp @@ -43,27 +43,27 @@ void CommandBuffer::dispatchCompute(ComputeInstance *shader, int32_t groupsX, in A_UNUSED(groupsZ); } /*! - Draws a \a mesh with the specified \a sub mesh index in the \a transform location with assigned \a material, and rendering \a layer. + Draws a \a mesh with the specified \a sub mesh index in the \a transform location with assigned material \a instance, and rendering \a layer. */ -void CommandBuffer::drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *material) { +void CommandBuffer::drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) { A_UNUSED(transform); A_UNUSED(mesh); A_UNUSED(sub); A_UNUSED(layer); - A_UNUSED(material); + A_UNUSED(instance); } /*! Draws the same \a mesh multiple times using GPU instancing. - GPU will draw this mesh with the specified \a sub mesh index in different \a transform locations with assigned \a material, and rendering \a layer. + GPU will draw this mesh with the specified \a sub mesh index in different \a transform locations with assigned material \a instance, and rendering \a layer. Parameter \a count specifies the number of instances to draw. */ -void CommandBuffer::drawMeshInstanced(const Matrix4 *transform, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *material) { +void CommandBuffer::drawMeshInstanced(const Matrix4 *transform, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) { A_UNUSED(transform); A_UNUSED(count); A_UNUSED(mesh); A_UNUSED(sub); A_UNUSED(layer); - A_UNUSED(material); + A_UNUSED(instance); } /*! Sets the render \a target for subsequent rendering commands. diff --git a/engine/src/components/particlerender.cpp b/engine/src/components/particlerender.cpp index d0fc8e87c..4c526bb6e 100644 --- a/engine/src/components/particlerender.cpp +++ b/engine/src/components/particlerender.cpp @@ -139,11 +139,13 @@ void ParticleRender::draw(CommandBuffer &buffer, uint32_t layer) { buffer.setObjectId(a->uuid()); for(uint32_t index = 0; index < m_buffers.size(); index++) { - if(m_visibleCount[index] > 0 && m_materials[index]) { - buffer.setMaterialId(m_materials[index]->material()->uuid()); + MaterialInstance *instance = m_materials[index]; + if(m_visibleCount[index] > 0 && instance) { + buffer.setMaterialId(instance->material()->uuid()); ParticleEmitter *emitter = m_effect->emitter(index); - buffer.drawMeshInstanced(m_buffers[index].data(), m_visibleCount[index], emitter->mesh(), 0, layer, m_materials[index]); + Matrix4 *transforms = m_buffers[index].data(); + buffer.drawMeshInstanced(transforms, m_visibleCount[index], emitter->mesh(), 0, layer, instance); } } } diff --git a/engine/src/components/spriterender.cpp b/engine/src/components/spriterender.cpp index 77d5aaa7f..e24ff680e 100644 --- a/engine/src/components/spriterender.cpp +++ b/engine/src/components/spriterender.cpp @@ -70,9 +70,7 @@ void SpriteRender::draw(CommandBuffer &buffer, uint32_t layer) { buffer.setColor(m_color); buffer.setMaterialId(material()->uuid()); - buffer.drawMesh(t->worldTransform(), - (m_customMesh) ? m_customMesh : m_mesh, - 0, layer, m_materials.front()); + buffer.drawMesh(t->worldTransform(), (m_customMesh) ? m_customMesh : m_mesh, 0, layer, m_materials.front()); } } } diff --git a/modules/editor/shadertools/shaders/ShaderLayout.h b/modules/editor/shadertools/shaders/ShaderLayout.h index 04a3d5220..86aab5dfc 100644 --- a/modules/editor/shadertools/shaders/ShaderLayout.h +++ b/modules/editor/shadertools/shaders/ShaderLayout.h @@ -22,14 +22,19 @@ layout(set = 1, binding = GLOBAL) uniform Global { float padding[13]; } g; -layout(binding = LOCAL) uniform Local { - mat4 model; +layout(binding = LOCAL) uniform sampler2D instanceMap; - vec4 color; +layout(binding = LOCAL + 1) uniform sampler2D radianceMap; - vec4 objectId; +mat4 getModelMatrix() { + float width = 1.0 / 512.0; + int x = gl_InstanceID * 8; + int y = 0; - vec4 materialId; -} l; + vec4 m1 = texture(instanceMap, vec2(x, y) * width); + vec4 m2 = texture(instanceMap, vec2(x + 1, y) * width); + vec4 m3 = texture(instanceMap, vec2(x + 2, y) * width); + vec4 m4 = texture(instanceMap, vec2(x + 3, y) * width); -layout(binding = LOCAL + 1) uniform sampler2D radianceMap; + return mat4(m1, m2, m3, m4); +} diff --git a/modules/editor/shadertools/shaders/Skinned.vert b/modules/editor/shadertools/shaders/Skinned.vert index 2f23ea39d..62ae605d2 100644 --- a/modules/editor/shadertools/shaders/Skinned.vert +++ b/modules/editor/shadertools/shaders/Skinned.vert @@ -15,10 +15,6 @@ layout(location = 2) in vec4 color; layout(location = 5) in vec4 skinnedBones; layout(location = 6) in vec4 skinnedWeights; -#ifdef INSTANCING - layout(location = 7) in mat4 instanceMatrix; -#endif - layout(location = 0) out vec4 _vertex; layout(location = 1) out vec2 _uv0; layout(location = 2) out vec4 _color; diff --git a/modules/editor/shadertools/shaders/Static.vert b/modules/editor/shadertools/shaders/Static.vert index 37f04bca8..d4b6f5b8e 100644 --- a/modules/editor/shadertools/shaders/Static.vert +++ b/modules/editor/shadertools/shaders/Static.vert @@ -12,10 +12,6 @@ layout(location = 2) in vec4 color; layout(location = 4) in vec3 tangent; #endif -#ifdef INSTANCING - layout(location = 7) in mat4 instanceMatrix; -#endif - layout(location = 0) out vec4 _vertex; layout(location = 1) out vec2 _uv0; layout(location = 2) out vec4 _color; @@ -32,12 +28,7 @@ layout(location = 7) out mat4 _modelView; #pragma functions void main(void) { - #ifdef INSTANCING - mat4 model = instanceMatrix; - #else - mat4 model = l.model; - #endif - _modelView = g.view * model; + _modelView = g.view * getModelMatrix(); vec3 camera = vec3(g.view[0].w, g.view[1].w, diff --git a/modules/renders/rendergl/includes/commandbuffergl.h b/modules/renders/rendergl/includes/commandbuffergl.h index 829e80b2a..aa794f9f0 100644 --- a/modules/renders/rendergl/includes/commandbuffergl.h +++ b/modules/renders/rendergl/includes/commandbuffergl.h @@ -28,9 +28,9 @@ class CommandBufferGL : public CommandBuffer { void dispatchCompute(ComputeInstance *shader, int32_t groupsX, int32_t groupsY, int32_t groupsZ) override; - void drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *material = nullptr) override; + void drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) override; - void drawMeshInstanced(const Matrix4 *models, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *material = nullptr) override; + void drawMeshInstanced(const Matrix4 *models, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) override; void setRenderTarget(RenderTarget *target, uint32_t level = 0) override; diff --git a/modules/renders/rendergl/includes/resources/meshgl.h b/modules/renders/rendergl/includes/resources/meshgl.h index 2b3f564f9..20714bb7f 100644 --- a/modules/renders/rendergl/includes/resources/meshgl.h +++ b/modules/renders/rendergl/includes/resources/meshgl.h @@ -28,8 +28,6 @@ class MeshGL : public Mesh { void bindVao(CommandBufferGL *buffer); - uint32_t instance() const; - protected: void updateVao(); void updateVbo(CommandBufferGL *buffer); @@ -38,9 +36,8 @@ class MeshGL : public Mesh { uint32_t m_triangles; uint32_t m_vertices; - uint32_t m_instanceBuffer; - list m_vao; + }; #endif // MESHGL_H diff --git a/modules/renders/rendergl/src/commandbuffergl.cpp b/modules/renders/rendergl/src/commandbuffergl.cpp index 236b2c4f0..b6b38fb8d 100644 --- a/modules/renders/rendergl/src/commandbuffergl.cpp +++ b/modules/renders/rendergl/src/commandbuffergl.cpp @@ -84,69 +84,37 @@ void CommandBufferGL::dispatchCompute(ComputeInstance *shader, int32_t groupsX, #endif } -void CommandBufferGL::drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *material) { +void CommandBufferGL::drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) { PROFILE_FUNCTION(); - if(mesh && material) { - MeshGL *m = static_cast(mesh); - - MaterialInstanceGL *instance = static_cast(material); - if(instance->bind(this, layer)) { - m_local.model = model; - - glBindBuffer(GL_UNIFORM_BUFFER, m_localUbo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Local), &m_local); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - m->bindVao(this); - - if(m->indices().empty()) { - uint32_t vert = m->vertices().size(); - int32_t glMode = (material->material()->wireframe()) ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; - glDrawArrays(glMode, 0, vert); - PROFILER_STAT(POLYGONS, vert - 2); - } else { - int32_t indexStart = m->indexStart(sub); - int32_t indexCount = m->indexCount(sub); - int32_t glMode = (material->material()->wireframe()) ? GL_LINES : GL_TRIANGLES; - glDrawElements(glMode, indexCount, GL_UNSIGNED_INT, reinterpret_cast(indexStart * sizeof(int32_t))); - PROFILER_STAT(POLYGONS, indexCount / 3); - } - PROFILER_STAT(DRAWCALLS, 1); - - glBindVertexArray(0); - } - } + drawMeshInstanced(&model, 1, mesh, sub, layer, instance); } void CommandBufferGL::drawMeshInstanced(const Matrix4 *models, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *material) { PROFILE_FUNCTION(); if(mesh && material) { - MeshGL *m = static_cast(mesh); + MeshGL *meshGL = static_cast(mesh); - m_local.model.identity(); + m_local.model = *models; glBindBuffer(GL_UNIFORM_BUFFER, m_localUbo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Local), &m_local); glBindBuffer(GL_UNIFORM_BUFFER, 0); - MaterialInstanceGL *instance = static_cast(material); - if(instance->bind(this, layer)) { - glBindBuffer(GL_ARRAY_BUFFER, m->instance()); - glBufferData(GL_ARRAY_BUFFER, count * sizeof(Matrix4), models, GL_DYNAMIC_DRAW); - - m->bindVao(this); + MaterialInstanceGL *instanceGL = static_cast(material); + if(instanceGL->bind(this, layer)) { + meshGL->bindVao(this); - if(m->indices().empty()) { + if(meshGL->indices().empty()) { int32_t glMode = (material->material()->wireframe()) ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; - uint32_t vert = m->vertices().size(); + uint32_t vert = meshGL->vertices().size(); glDrawArraysInstanced(glMode, 0, vert, count); PROFILER_STAT(POLYGONS, index - 2 * count); } else { - int32_t index = m->indexCount(sub); + int32_t index = meshGL->indexCount(sub); int32_t glMode = (material->material()->wireframe()) ? GL_LINES : GL_TRIANGLES; - glDrawElementsInstanced(glMode, index, GL_UNSIGNED_INT, reinterpret_cast(m->indexStart(sub) * sizeof(int32_t)), count); + glDrawElementsInstanced(glMode, index, GL_UNSIGNED_INT, reinterpret_cast(meshGL->indexStart(sub) * sizeof(int32_t)), count); PROFILER_STAT(POLYGONS, (index / 3) * count); } PROFILER_STAT(DRAWCALLS, 1); diff --git a/modules/renders/rendergl/src/resources/meshgl.cpp b/modules/renders/rendergl/src/resources/meshgl.cpp index 1a96e580c..8134760aa 100644 --- a/modules/renders/rendergl/src/resources/meshgl.cpp +++ b/modules/renders/rendergl/src/resources/meshgl.cpp @@ -6,8 +6,8 @@ MeshGL::MeshGL() : m_triangles(0), - m_vertices(0), - m_instanceBuffer(0) { + m_vertices(0) { + } void MeshGL::bindVao(CommandBufferGL *buffer) { @@ -29,11 +29,6 @@ void MeshGL::bindVao(CommandBufferGL *buffer) { glDeleteBuffers(1, &m_triangles); m_triangles = 0; - if(m_instanceBuffer != 0) { - glDeleteBuffers(1, &m_instanceBuffer); - m_instanceBuffer = 0; - } - // Destroy all VAOs for(auto &it : m_vao) { if(it->buffer == buffer) { @@ -130,19 +125,9 @@ void MeshGL::updateVao() { glVertexAttribPointer(WEIGHTS_ATRIB, 4, GL_FLOAT, GL_FALSE, 0, reinterpret_cast(offset)); } - glBindBuffer(GL_ARRAY_BUFFER, m_instanceBuffer); - for(uint32_t i = 0; i < 4; i++) { - glEnableVertexAttribArray(INSTANCE_ATRIB + i); - glVertexAttribPointer(INSTANCE_ATRIB + i, 4, GL_FLOAT, GL_FALSE, sizeof(Matrix4), reinterpret_cast(i * sizeof(Vector4))); - glVertexAttribDivisor(INSTANCE_ATRIB + i, 1); - } } void MeshGL::updateVbo(CommandBufferGL *buffer) { - if(!m_instanceBuffer) { - glGenBuffers(1, &m_instanceBuffer); - } - bool dynamic = isDynamic(); uint32_t usage = (dynamic) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW; uint32_t vCount = vertices().size(); @@ -216,7 +201,3 @@ void MeshGL::updateVbo(CommandBufferGL *buffer) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0); } - -uint32_t MeshGL::instance() const { - return m_instanceBuffer; -} From 200bda787677d0806cf4eb643400026a49dcd214 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Wed, 10 Apr 2024 15:06:11 +0300 Subject: [PATCH 2/6] update --- .../shadertools/converter/shaderbuilder.cpp | 24 ++++++------ .../shadertools/converter/shaderbuilder.h | 2 - .../shadertools/converter/shadernodegraph.cpp | 14 ++----- .../shadertools/converter/spirvconverter.h | 4 +- .../editor/shadertools/shaders/Billboard.vert | 7 +++- .../editor/shadertools/shaders/Default.vert | 39 ------------------- .../editor/shadertools/shaders/Shader.frag | 16 ++++++-- .../editor/shadertools/shaders/ShaderLayout.h | 13 ------- .../editor/shadertools/shaders/Skinned.vert | 16 ++++---- .../editor/shadertools/shaders/Static.vert | 8 +++- .../shadertools/shaders/VertexFactory.h | 30 ++++++++++++++ modules/editor/shadertools/shadertools.qrc | 2 +- worldeditor/bin/editor/materials/debug.shader | 10 ++--- worldeditor/bin/editor/materials/grid.shader | 6 +-- .../bin/engine/materials/DefaultFont.shader | 5 ++- worldeditor/bin/engine/materials/Link.shader | 4 +- 16 files changed, 90 insertions(+), 110 deletions(-) delete mode 100644 modules/editor/shadertools/shaders/Default.vert create mode 100644 modules/editor/shadertools/shaders/VertexFactory.h diff --git a/modules/editor/shadertools/converter/shaderbuilder.cpp b/modules/editor/shadertools/converter/shaderbuilder.cpp index 6d01ca881..b876be447 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.cpp +++ b/modules/editor/shadertools/converter/shaderbuilder.cpp @@ -216,12 +216,7 @@ AssetConverter::ReturnCode ShaderBuilder::convertFile(AssetConverterSettings *se } data[ATTRIBUTES] = attributes; - auto it = data.find(STATICINST); - if(it != data.end()) { - data[STATICINST] = compile(rhi, it->second.toString(), inputs, EShLangVertex); - } - - it = data.find(PARTICLE); + auto it = data.find(PARTICLE); if(it != data.end()) { data[PARTICLE] = compile(rhi, it->second.toString(), inputs, EShLangVertex); } @@ -236,6 +231,11 @@ AssetConverter::ReturnCode ShaderBuilder::convertFile(AssetConverterSettings *se data[FULLSCREEN] = compile(rhi, it->second.toString(), inputs, EShLangVertex); } + it = data.find(GEOMETRY); + if(it != data.end()) { + data[GEOMETRY] = compile(rhi, it->second.toString(), inputs, EShLangGeometry); + } + VariantList result; VariantList object; @@ -342,10 +342,6 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo user[FRAGMENT] = loadShader(str, define, pragmas); } } else { - if(materialType == Material::PostProcess) { - define += "\n#define TYPE_FULLSCREEN\n"; - } - if(currentRhi() == ShaderBuilderSettings::Rhi::Vulkan) { define += "\n#define VULKAN\n"; } @@ -362,12 +358,16 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo if(!str.empty()) { user[STATIC] = loadShader(str, define, pragmas); } else { - user[STATIC] = loadIncludes("Default.vert", define, pragmas); + string file = "Default.vert"; + if(materialType == Material::PostProcess) { + file = "Fullscreen.vert"; + } + user[STATIC] = loadIncludes(file, define, pragmas); } str = shaders[gGeometry]; if(!str.empty()) { - user[STATIC] = loadShader(GEOMETRY, define, pragmas); + user[GEOMETRY] = loadShader(str, define, pragmas); } } } diff --git a/modules/editor/shadertools/converter/shaderbuilder.h b/modules/editor/shadertools/converter/shaderbuilder.h index 319632a11..c8d34bcfa 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.h +++ b/modules/editor/shadertools/converter/shaderbuilder.h @@ -11,9 +11,7 @@ #define VISIBILITY "Visibility" #define STATIC "Static" -#define STATICINST "StaticInst" #define SKINNED "Skinned" -#define SKINNEDINST "SkinnedInst" #define PARTICLE "Particle" #define FULLSCREEN "Fullscreen" diff --git a/modules/editor/shadertools/converter/shadernodegraph.cpp b/modules/editor/shadertools/converter/shadernodegraph.cpp index 815f9cf7f..ccd3e473d 100644 --- a/modules/editor/shadertools/converter/shadernodegraph.cpp +++ b/modules/editor/shadertools/converter/shadernodegraph.cpp @@ -675,13 +675,6 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) const { } } if(root->materialType() == ShaderRootNode::Surface && !editor) { - { - string localDefine = define + "\n#define INSTANCING"; - Variant data = ShaderBuilder::loadIncludes("Static.vert", localDefine, m_pragmas); - if(data.isValid()) { - user[STATICINST] = data; - } - } { Variant data = ShaderBuilder::loadIncludes("Skinned.vert", define, m_pragmas); if(data.isValid()) { @@ -753,7 +746,6 @@ QString ShaderNodeGraph::buildFrom(GraphNode *node, Stage stage) { ShaderNode *f = dynamic_cast(node); if(f) { if(stage == Vertex) { - result = "\tvec3 PositionOffset = vec3(0.0);\n"; return result; } @@ -767,7 +759,7 @@ QString ShaderNodeGraph::buildFrom(GraphNode *node, Stage stage) { } } - QString type = "\tvec3 Emissive = %1;\n"; + QString type = "\tEmissive = %1;\n"; int32_t size = 0; int32_t index = f->build(result, stack, link, depth, size); @@ -780,7 +772,7 @@ QString ShaderNodeGraph::buildFrom(GraphNode *node, Stage stage) { } else { result.append(type.arg("vec3(0.0)")); } - result.append("\tfloat Opacity = 1.0;\n"); + result.append("\tOpacity = 1.0;\n"); } else { for(NodePort &port : node->ports()) { // Iterate all ports for the node if(port.m_out == false && port.m_userFlags == stage) { @@ -836,7 +828,7 @@ QString ShaderNodeGraph::buildFrom(GraphNode *node, Stage stage) { } } - result.append(QString("\t%1 %2 = %3;\n").arg(type, name, value)); + result.append(QString("\t%1 = %2;\n").arg(name, value)); } } } diff --git a/modules/editor/shadertools/converter/spirvconverter.h b/modules/editor/shadertools/converter/spirvconverter.h index fe4929f8e..73a18c40b 100644 --- a/modules/editor/shadertools/converter/spirvconverter.h +++ b/modules/editor/shadertools/converter/spirvconverter.h @@ -186,10 +186,10 @@ class SpirVConverter { return spirv; } } else { - aError() << program.getInfoLog(); + aError() << "[Program]" << program.getInfoLog(); } } else { - aError() << shader.getInfoLog(); + aError() << "[Shader]" << shader.getInfoLog(); } return vector(); } diff --git a/modules/editor/shadertools/shaders/Billboard.vert b/modules/editor/shadertools/shaders/Billboard.vert index 1302cad0d..49243e239 100644 --- a/modules/editor/shadertools/shaders/Billboard.vert +++ b/modules/editor/shadertools/shaders/Billboard.vert @@ -3,6 +3,7 @@ #pragma flags #include "ShaderLayout.h" +#include "VertexFactory.h" layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; @@ -33,7 +34,7 @@ layout(location = 7) out mat4 _modelView; #pragma functions void main(void) { - mat4 model = l.model; + mat4 model = getModelMatrix(); _modelView = g.view * model; @@ -41,6 +42,8 @@ void main(void) { g.view[1].w, g.view[2].w); + vec3 PositionOffset = vec3(0.0f); + #pragma vertex float angle = particlePosRot.w; // rotation @@ -64,7 +67,7 @@ void main(void) { _vertex = g.projection * (_modelView * v); _view = normalize((model * v).xyz - camera); - _color = color; + _color = color * getLocalColor(); _uv0 = uv0; gl_Position = _vertex; } diff --git a/modules/editor/shadertools/shaders/Default.vert b/modules/editor/shadertools/shaders/Default.vert deleted file mode 100644 index cb22c2546..000000000 --- a/modules/editor/shadertools/shaders/Default.vert +++ /dev/null @@ -1,39 +0,0 @@ -#version 450 core - -#pragma flags - -#include "ShaderLayout.h" - -#pragma uniforms - -layout(location = 0) in vec3 vertex; -layout(location = 1) in vec2 uv0; -layout(location = 2) in vec4 color; - -layout(location = 3) in vec3 normal; -layout(location = 4) in vec3 tangent; - -layout(location = 0) out vec4 _vertex; -layout(location = 1) out vec2 _uv0; -layout(location = 2) out vec4 _color; -layout(location = 3) out vec3 _n; -layout(location = 4) out vec3 _t; -layout(location = 5) out vec3 _b; - -void main(void) { -#ifdef TYPE_FULLSCREEN - _vertex = vec4(vertex * 2.0, 1.0); -#else - mat4 mv = g.view * l.model; - mat3 rot = mat3(l.model); - - _t = normalize(rot * tangent); - _n = normalize(rot * normal); - _b = cross(_t, _n); - _vertex = g.projection * (mv * vec4(vertex, 1.0)); -#endif - - _color = color; - _uv0 = uv0; - gl_Position = _vertex; -} diff --git a/modules/editor/shadertools/shaders/Shader.frag b/modules/editor/shadertools/shaders/Shader.frag index 3d626793c..4c63bae7b 100644 --- a/modules/editor/shadertools/shaders/Shader.frag +++ b/modules/editor/shadertools/shaders/Shader.frag @@ -30,17 +30,25 @@ layout(location = 3) out vec4 gbuffer3; #pragma functions void main(void) { + vec3 Diffuse; + vec3 Emissive; + vec3 Normal; + float Metallic; + float Roughness; + float Opacity; + float IOR; + #pragma fragment - float alpha = Opacity * l.color.w; + float alpha = Opacity * _color.w; if(g.clip >= alpha) { discard; } - vec3 emit = Emissive * l.color.xyz; + vec3 emit = Emissive * _color.xyz; #ifdef VISIBILITY_BUFFER - gbuffer0 = l.objectId; + gbuffer0 = vec4(0);//l.objectId; return; #endif @@ -51,7 +59,7 @@ void main(void) { #ifdef BLEND_OPAQUE float model = 0.0f; vec3 normal = vec3(1.0f); - vec3 albedo = Diffuse * l.color.xyz; + vec3 albedo = Diffuse * _color.xyz; #ifdef MODEL_LIT normal = Normal * 2.0f - 1.0f; diff --git a/modules/editor/shadertools/shaders/ShaderLayout.h b/modules/editor/shadertools/shaders/ShaderLayout.h index 86aab5dfc..203a52dab 100644 --- a/modules/editor/shadertools/shaders/ShaderLayout.h +++ b/modules/editor/shadertools/shaders/ShaderLayout.h @@ -25,16 +25,3 @@ layout(set = 1, binding = GLOBAL) uniform Global { layout(binding = LOCAL) uniform sampler2D instanceMap; layout(binding = LOCAL + 1) uniform sampler2D radianceMap; - -mat4 getModelMatrix() { - float width = 1.0 / 512.0; - int x = gl_InstanceID * 8; - int y = 0; - - vec4 m1 = texture(instanceMap, vec2(x, y) * width); - vec4 m2 = texture(instanceMap, vec2(x + 1, y) * width); - vec4 m3 = texture(instanceMap, vec2(x + 2, y) * width); - vec4 m4 = texture(instanceMap, vec2(x + 3, y) * width); - - return mat4(m1, m2, m3, m4); -} diff --git a/modules/editor/shadertools/shaders/Skinned.vert b/modules/editor/shadertools/shaders/Skinned.vert index 62ae605d2..334667dbd 100644 --- a/modules/editor/shadertools/shaders/Skinned.vert +++ b/modules/editor/shadertools/shaders/Skinned.vert @@ -3,6 +3,9 @@ #pragma flags #include "ShaderLayout.h" +#include "VertexFactory.h" + +layout(binding = LOCAL + 2) uniform sampler2D skinMatrices; layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; @@ -29,22 +32,19 @@ layout(location = 7) out mat4 _modelView; #pragma uniforms -layout(binding = LOCAL + 2) uniform sampler2D skinMatrices; - #pragma functions void main(void) { -#ifdef INSTANCING - mat4 model = instanceMatrix; -#else - mat4 model = l.model; -#endif + mat4 model = getModelMatrix(); + _modelView = g.view * model; vec3 camera = vec3(g.view[0].w, g.view[1].w, g.view[2].w); + vec3 PositionOffset = vec3(0.0f); + #pragma vertex vec4 bones = skinnedBones; @@ -86,7 +86,7 @@ void main(void) { _vertex = g.projection * (g.view * vec4(v, 1.0)); _view = normalize(v - g.cameraPosition.xyz); - _color = color; + _color = color * getLocalColor(); _uv0 = uv0; gl_Position = _vertex; } diff --git a/modules/editor/shadertools/shaders/Static.vert b/modules/editor/shadertools/shaders/Static.vert index d4b6f5b8e..e11b95172 100644 --- a/modules/editor/shadertools/shaders/Static.vert +++ b/modules/editor/shadertools/shaders/Static.vert @@ -3,6 +3,7 @@ #pragma flags #include "ShaderLayout.h" +#include "VertexFactory.h" layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; @@ -28,12 +29,15 @@ layout(location = 7) out mat4 _modelView; #pragma functions void main(void) { - _modelView = g.view * getModelMatrix(); + mat4 model = getModelMatrix(); + _modelView = g.view * model; vec3 camera = vec3(g.view[0].w, g.view[1].w, g.view[2].w); + vec3 PositionOffset = vec3(0.0f); + #pragma vertex #ifdef MODEL_LIT @@ -46,7 +50,7 @@ void main(void) { _vertex = g.projection * (_modelView * v); _view = normalize((model * v).xyz - g.cameraPosition.xyz); - _color = color; + _color = color * getLocalColor(); _uv0 = uv0; gl_Position = _vertex; } diff --git a/modules/editor/shadertools/shaders/VertexFactory.h b/modules/editor/shadertools/shaders/VertexFactory.h new file mode 100644 index 000000000..cdca4c8a8 --- /dev/null +++ b/modules/editor/shadertools/shaders/VertexFactory.h @@ -0,0 +1,30 @@ +const int structSize = 8; + +ivec3 getTextureCoord(int offset) { + ivec3 result; + + result.z = textureSize(instanceMap, 0).x; + result.x = gl_InstanceIndex * structSize + offset; + result.y = 0; + + return result; +} + +mat4 getModelMatrix() { + ivec3 offset = getTextureCoord(0); + float width = 1.0 / offset.z; + + vec4 m1 = textureLod(instanceMap, vec2(offset.x, offset.y) * width, 0); + vec4 m2 = textureLod(instanceMap, vec2(offset.x + 1, offset.y) * width, 0); + vec4 m3 = textureLod(instanceMap, vec2(offset.x + 2, offset.y) * width, 0); + vec4 m4 = textureLod(instanceMap, vec2(offset.x + 3, offset.y) * width, 0); + + return mat4(m1, m2, m3, m4); +} + +vec4 getLocalColor() { + ivec3 offset = getTextureCoord(4); + float width = 1.0 / offset.z; + + return textureLod(instanceMap, vec2(offset.xy) * width, 0); +} diff --git a/modules/editor/shadertools/shadertools.qrc b/modules/editor/shadertools/shadertools.qrc index a8d73670e..437aee4a5 100644 --- a/modules/editor/shadertools/shadertools.qrc +++ b/modules/editor/shadertools/shadertools.qrc @@ -3,7 +3,7 @@ shaders/BRDF.h shaders/ShaderLayout.h shaders/Default.frag - shaders/Default.vert + shaders/VertexFactory.h templates/Material.mtl shaders/functions/hsvToRgb.mtlf shaders/functions/gammaToLinear.mtlf diff --git a/worldeditor/bin/editor/materials/debug.shader b/worldeditor/bin/editor/materials/debug.shader index ecdb10449..076092e1c 100644 --- a/worldeditor/bin/editor/materials/debug.shader +++ b/worldeditor/bin/editor/materials/debug.shader @@ -1,6 +1,5 @@ - diff --git a/worldeditor/bin/engine/materials/Link.shader b/worldeditor/bin/engine/materials/Link.shader index 4d93ba490..87fc24671 100644 --- a/worldeditor/bin/engine/materials/Link.shader +++ b/worldeditor/bin/engine/materials/Link.shader @@ -6,7 +6,7 @@ #version 450 core #include "ShaderLayout.h" -#include "Functions.h" +#include "VertexFactory.h" #pragma flags @@ -17,7 +17,7 @@ layout(location = 0) out vec4 _color; void main(void) { _color = color; - gl_Position = g.projection * ((g.view * l.model) * vec4(vertex, 1.0)); + gl_Position = g.projection * ((g.view * getModelMatrix()) * vec4(vertex, 1.0)); } ]]> Date: Wed, 24 Apr 2024 10:14:44 +0300 Subject: [PATCH 3/6] Update --- engine/src/components/camera.cpp | 2 +- engine/src/components/spriterender.cpp | 8 ++-- engine/src/components/tilemaprender.cpp | 5 ++- .../src/editor/converters/assimpconverter.cpp | 2 +- engine/src/gizmos.cpp | 4 +- .../shadertools/converter/shaderbuilder.cpp | 2 +- .../editor/shadertools/shaders/Billboard.vert | 2 + .../editor/shadertools/shaders/ShaderLayout.h | 4 +- .../editor/shadertools/shaders/Skinned.vert | 2 + .../editor/shadertools/shaders/Static.vert | 12 +++-- .../shadertools/shaders/VertexFactory.h | 28 +++--------- .../converter/textureconverter.cpp | 2 +- .../rendergl/includes/commandbuffergl.h | 6 +-- .../renders/rendergl/src/commandbuffergl.cpp | 22 +++++---- modules/uikit/src/components/image.cpp | 7 +-- .../bin/engine/materials/DefaultSprite.mtl | 45 ------------------- .../bin/engine/materials/DefaultSprite.shader | 26 +++++++++++ ...prite.mtl.set => DefaultSprite.shader.set} | 0 18 files changed, 75 insertions(+), 104 deletions(-) delete mode 100644 worldeditor/bin/engine/materials/DefaultSprite.mtl create mode 100644 worldeditor/bin/engine/materials/DefaultSprite.shader rename worldeditor/bin/engine/materials/{DefaultSprite.mtl.set => DefaultSprite.shader.set} (100%) diff --git a/engine/src/components/camera.cpp b/engine/src/components/camera.cpp index f0cd7e079..da68d69d6 100644 --- a/engine/src/components/camera.cpp +++ b/engine/src/components/camera.cpp @@ -286,7 +286,7 @@ array Camera::frustumCorners(bool ortho, float sigma, float ratio, c void Camera::drawGizmos() { Transform *t = transform(); - Gizmos::drawIcon(t->worldPosition(), Vector2(0.5f), ".embedded/camera.png", color()); + Gizmos::drawIcon(t->worldPosition(), Vector2(0.5f), ".embedded/camera.png", Vector4(1.0f)); } void Camera::drawGizmosSelected() { diff --git a/engine/src/components/spriterender.cpp b/engine/src/components/spriterender.cpp index e24ff680e..ddb54c67a 100644 --- a/engine/src/components/spriterender.cpp +++ b/engine/src/components/spriterender.cpp @@ -13,8 +13,8 @@ namespace { const char *gBaseMap = "BaseMap"; - const char *gOverride = "texture0"; - const char *gDefaultSprite = ".embedded/DefaultSprite.mtl"; + const char *gOverride = "mainTexture"; + const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; } static hash hash_str; @@ -369,6 +369,7 @@ bool SpriteRender::composeSliced(Mesh *mesh, Vector2 &size, Vector3 &delta, floa bool SpriteRender::composeTiled(Mesh *mesh, Vector2 &size, Vector3 &delta, float scale) { Vector3Vector &verts = mesh->vertices(); Vector2Vector &uvs = mesh->uv0(); + Vector4Vector &colors = mesh->colors(); IndexVector &indices = mesh->indices(); Vector2 ubl(uvs[0]); @@ -383,6 +384,7 @@ bool SpriteRender::composeTiled(Mesh *mesh, Vector2 &size, Vector3 &delta, float verts.resize(width * height * 4); uvs.resize(width * height * 4); + colors.resize(width * height * 4, Vector4(1.0f)); indices.resize(width * height * 6); Vector3 bl(Vector3(size, 0.0f) * -0.5f); @@ -410,7 +412,7 @@ bool SpriteRender::composeTiled(Mesh *mesh, Vector2 &size, Vector3 &delta, float uvs[index + 2] = ubl + Vector2((utr.x - ubl.x) * f.x, (utr.y - ubl.y) * f.y); uvs[index + 3] = ubl + Vector2(0.0f, (utr.y - ubl.y) * f.y); - indices[i] = index; + indices[i] = index; indices[i + 1] = index + 1; indices[i + 2] = index + 2; indices[i + 3] = index; diff --git a/engine/src/components/tilemaprender.cpp b/engine/src/components/tilemaprender.cpp index baccccac6..542738d2e 100644 --- a/engine/src/components/tilemaprender.cpp +++ b/engine/src/components/tilemaprender.cpp @@ -15,7 +15,8 @@ namespace { const char *gTileMap = "TileMap"; const char *gMaterial = "Material"; - const char *gOverride = "texture0"; + const char *gOverride = "mainTexture"; + const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; } /*! @@ -167,7 +168,7 @@ VariantMap TileMapRender::saveUserData() const { \internal */ void TileMapRender::composeComponent() { - setMaterial(Engine::loadResource(".embedded/DefaultSprite.mtl")); + setMaterial(Engine::loadResource(gDefaultSprite)); } /*! \internal diff --git a/engine/src/editor/converters/assimpconverter.cpp b/engine/src/editor/converters/assimpconverter.cpp index 626e080eb..0fab18b6b 100644 --- a/engine/src/editor/converters/assimpconverter.cpp +++ b/engine/src/editor/converters/assimpconverter.cpp @@ -382,7 +382,7 @@ Mesh *AssimpConverter::importMesh(const aiScene *scene, const aiNode *element, A vertices.resize(count_v); Vector4Vector &colors = mesh->colors(); - colors.resize(count_v); + colors.resize(count_v, Vector4(1.0f)); Vector2Vector &uv0 = mesh->uv0(); uv0.resize(count_v); diff --git a/engine/src/gizmos.cpp b/engine/src/gizmos.cpp index 3d50c8fcb..4f515f0b3 100644 --- a/engine/src/gizmos.cpp +++ b/engine/src/gizmos.cpp @@ -8,7 +8,7 @@ #include "commandbuffer.h" -#define OVERRIDE "texture0" +#define OVERRIDE "mainTexture" Mesh *Gizmos::s_wire = nullptr; Mesh *Gizmos::s_solid = nullptr; @@ -53,7 +53,7 @@ void Gizmos::init() { } } if(s_spriteMaterial == nullptr) { - s_spriteMaterial = Engine::loadResource(".embedded/DefaultSprite.mtl"); + s_spriteMaterial = Engine::loadResource(".embedded/DefaultSprite.shader"); } if(s_wire == nullptr) { diff --git a/modules/editor/shadertools/converter/shaderbuilder.cpp b/modules/editor/shadertools/converter/shaderbuilder.cpp index b876be447..27534ba75 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.cpp +++ b/modules/editor/shadertools/converter/shaderbuilder.cpp @@ -358,7 +358,7 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo if(!str.empty()) { user[STATIC] = loadShader(str, define, pragmas); } else { - string file = "Default.vert"; + string file = "Static.vert"; if(materialType == Material::PostProcess) { file = "Fullscreen.vert"; } diff --git a/modules/editor/shadertools/shaders/Billboard.vert b/modules/editor/shadertools/shaders/Billboard.vert index 49243e239..286578688 100644 --- a/modules/editor/shadertools/shaders/Billboard.vert +++ b/modules/editor/shadertools/shaders/Billboard.vert @@ -34,6 +34,8 @@ layout(location = 7) out mat4 _modelView; #pragma functions void main(void) { +#pragma instance + mat4 model = getModelMatrix(); _modelView = g.view * model; diff --git a/modules/editor/shadertools/shaders/ShaderLayout.h b/modules/editor/shadertools/shaders/ShaderLayout.h index 203a52dab..dce5a1879 100644 --- a/modules/editor/shadertools/shaders/ShaderLayout.h +++ b/modules/editor/shadertools/shaders/ShaderLayout.h @@ -22,6 +22,8 @@ layout(set = 1, binding = GLOBAL) uniform Global { float padding[13]; } g; -layout(binding = LOCAL) uniform sampler2D instanceMap; +layout(std140, set = 1, binding = LOCAL) uniform InstanceData { + vec4 data[4096]; +} instance; layout(binding = LOCAL + 1) uniform sampler2D radianceMap; diff --git a/modules/editor/shadertools/shaders/Skinned.vert b/modules/editor/shadertools/shaders/Skinned.vert index 334667dbd..825c97d4b 100644 --- a/modules/editor/shadertools/shaders/Skinned.vert +++ b/modules/editor/shadertools/shaders/Skinned.vert @@ -35,6 +35,8 @@ layout(location = 7) out mat4 _modelView; #pragma functions void main(void) { +#pragma instance + mat4 model = getModelMatrix(); _modelView = g.view * model; diff --git a/modules/editor/shadertools/shaders/Static.vert b/modules/editor/shadertools/shaders/Static.vert index e11b95172..2fb34b716 100644 --- a/modules/editor/shadertools/shaders/Static.vert +++ b/modules/editor/shadertools/shaders/Static.vert @@ -29,8 +29,12 @@ layout(location = 7) out mat4 _modelView; #pragma functions void main(void) { - mat4 model = getModelMatrix(); - _modelView = g.view * model; +#pragma instance + + mat4 modelMatrix = getModelMatrix(); + vec4 localColor = getLocalColor(); + + _modelView = g.view * modelMatrix; vec3 camera = vec3(g.view[0].w, g.view[1].w, @@ -48,9 +52,9 @@ void main(void) { #endif vec4 v = vec4(vertex + PositionOffset, 1.0); _vertex = g.projection * (_modelView * v); - _view = normalize((model * v).xyz - g.cameraPosition.xyz); + _view = normalize((modelMatrix * v).xyz - g.cameraPosition.xyz); - _color = color * getLocalColor(); + _color = color * localColor; _uv0 = uv0; gl_Position = _vertex; } diff --git a/modules/editor/shadertools/shaders/VertexFactory.h b/modules/editor/shadertools/shaders/VertexFactory.h index cdca4c8a8..25ce72f2a 100644 --- a/modules/editor/shadertools/shaders/VertexFactory.h +++ b/modules/editor/shadertools/shaders/VertexFactory.h @@ -1,30 +1,12 @@ const int structSize = 8; -ivec3 getTextureCoord(int offset) { - ivec3 result; - - result.z = textureSize(instanceMap, 0).x; - result.x = gl_InstanceIndex * structSize + offset; - result.y = 0; - - return result; -} - mat4 getModelMatrix() { - ivec3 offset = getTextureCoord(0); - float width = 1.0 / offset.z; - - vec4 m1 = textureLod(instanceMap, vec2(offset.x, offset.y) * width, 0); - vec4 m2 = textureLod(instanceMap, vec2(offset.x + 1, offset.y) * width, 0); - vec4 m3 = textureLod(instanceMap, vec2(offset.x + 2, offset.y) * width, 0); - vec4 m4 = textureLod(instanceMap, vec2(offset.x + 3, offset.y) * width, 0); - - return mat4(m1, m2, m3, m4); + return mat4(instance.data[gl_InstanceIndex * structSize + 0], + instance.data[gl_InstanceIndex * structSize + 1], + instance.data[gl_InstanceIndex * structSize + 2], + instance.data[gl_InstanceIndex * structSize + 3]); } vec4 getLocalColor() { - ivec3 offset = getTextureCoord(4); - float width = 1.0 / offset.z; - - return textureLod(instanceMap, vec2(offset.xy) * width, 0); + return vec4(instance.data[gl_InstanceIndex * structSize + 4]); } diff --git a/modules/editor/texturetools/converter/textureconverter.cpp b/modules/editor/texturetools/converter/textureconverter.cpp index b6b15bd53..3f9594ace 100644 --- a/modules/editor/texturetools/converter/textureconverter.cpp +++ b/modules/editor/texturetools/converter/textureconverter.cpp @@ -424,7 +424,7 @@ Actor *TextureConverter::createActor(const AssetConverterSettings *settings, con SpriteRender *render = static_cast(object->component("SpriteRender")); if(render) { - render->setMaterial(Engine::loadResource(".embedded/DefaultSprite.mtl")); + render->setMaterial(Engine::loadResource(".embedded/DefaultSprite.shader")); Resource *res = Engine::loadResource(guid.toStdString()); Sprite *sheet = dynamic_cast(res); if(sheet) { diff --git a/modules/renders/rendergl/includes/commandbuffergl.h b/modules/renders/rendergl/includes/commandbuffergl.h index aa794f9f0..d83524ce5 100644 --- a/modules/renders/rendergl/includes/commandbuffergl.h +++ b/modules/renders/rendergl/includes/commandbuffergl.h @@ -12,16 +12,12 @@ #define BONES_ATRIB 5 #define WEIGHTS_ATRIB 6 -#define INSTANCE_ATRIB 7 - class CommandBufferGL : public CommandBuffer { A_OVERRIDE(CommandBufferGL, CommandBuffer, System) public: CommandBufferGL(); - ~CommandBufferGL() override; - void begin(); void clearRenderTarget(bool clearColor = true, const Vector4 &color = Vector4(0.0f), bool clearDepth = true, float depth = 1.0f) override; @@ -51,7 +47,7 @@ class CommandBufferGL : public CommandBuffer { protected: uint32_t m_globalUbo; - uint32_t m_localUbo; + uint32_t m_instanceUbo; }; diff --git a/modules/renders/rendergl/src/commandbuffergl.cpp b/modules/renders/rendergl/src/commandbuffergl.cpp index b6b38fb8d..de6db281b 100644 --- a/modules/renders/rendergl/src/commandbuffergl.cpp +++ b/modules/renders/rendergl/src/commandbuffergl.cpp @@ -12,15 +12,13 @@ #include #include +#define INSTANCE_SIZE 4096 + CommandBufferGL::CommandBufferGL() : m_globalUbo(0), - m_localUbo(0) { - PROFILE_FUNCTION(); - -} - -CommandBufferGL::~CommandBufferGL() { + m_instanceUbo(0) { + PROFILE_FUNCTION(); } void CommandBufferGL::begin() { @@ -43,13 +41,13 @@ void CommandBufferGL::begin() { glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Global), &m_globalUbo); glBindBuffer(GL_UNIFORM_BUFFER, 0); - if(m_localUbo == 0) { - glGenBuffers(1, &m_localUbo); - glBindBuffer(GL_UNIFORM_BUFFER, m_localUbo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(Local), nullptr, GL_DYNAMIC_DRAW); + if(m_instanceUbo == 0) { + glGenBuffers(1, &m_instanceUbo); + glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * INSTANCE_SIZE, nullptr, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); - glBindBufferBase(GL_UNIFORM_BUFFER, LOCAL_BIND, m_localUbo); + glBindBufferBase(GL_UNIFORM_BUFFER, LOCAL_BIND, m_instanceUbo); } } @@ -98,7 +96,7 @@ void CommandBufferGL::drawMeshInstanced(const Matrix4 *models, uint32_t count, M m_local.model = *models; - glBindBuffer(GL_UNIFORM_BUFFER, m_localUbo); + glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Local), &m_local); glBindBuffer(GL_UNIFORM_BUFFER, 0); diff --git a/modules/uikit/src/components/image.cpp b/modules/uikit/src/components/image.cpp index 9f886ef0f..37e38a9b0 100644 --- a/modules/uikit/src/components/image.cpp +++ b/modules/uikit/src/components/image.cpp @@ -14,9 +14,9 @@ namespace { const char *gMaterial = "Material"; const char *gBasemap = "BaseMap"; - const char *gOverride = "texture0"; - const char *gColor = "color0"; - const char *gDefaultSprite = ".embedded/DefaultSprite.mtl"; + const char *gOverride = "mainTexture"; + const char *gColor = "color"; + const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; }; static hash hash_str; @@ -66,6 +66,7 @@ void Image::draw(CommandBuffer &buffer) { buffer.setObjectId(actor()->uuid()); buffer.setMaterialId((m_customMaterial) ? m_customMaterial->material()->uuid() : m_material->material()->uuid()); + buffer.setColor(m_color); buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, (m_customMaterial) ? m_customMaterial : m_material); } diff --git a/worldeditor/bin/engine/materials/DefaultSprite.mtl b/worldeditor/bin/engine/materials/DefaultSprite.mtl deleted file mode 100644 index dff61cdee..000000000 --- a/worldeditor/bin/engine/materials/DefaultSprite.mtl +++ /dev/null @@ -1,45 +0,0 @@ - - - - - .embedded/invalid.png, Texture - - - 1, 1, 1, 1 - color0 - - - - true - false - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/worldeditor/bin/engine/materials/DefaultSprite.shader b/worldeditor/bin/engine/materials/DefaultSprite.shader new file mode 100644 index 000000000..07c8009e5 --- /dev/null +++ b/worldeditor/bin/engine/materials/DefaultSprite.shader @@ -0,0 +1,26 @@ + + + + + + + + + + diff --git a/worldeditor/bin/engine/materials/DefaultSprite.mtl.set b/worldeditor/bin/engine/materials/DefaultSprite.shader.set similarity index 100% rename from worldeditor/bin/engine/materials/DefaultSprite.mtl.set rename to worldeditor/bin/engine/materials/DefaultSprite.shader.set From 7d2519b986f9e1faa06fa2945f50e598913ba4fd Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Sat, 27 Apr 2024 07:58:42 +0300 Subject: [PATCH 4/6] update --- engine/includes/commandbuffer.h | 21 +- engine/includes/components/renderable.h | 2 +- engine/includes/components/spriterender.h | 2 + engine/includes/resources/material.h | 9 +- engine/src/commandbuffer.cpp | 24 +- engine/src/components/meshrender.cpp | 6 +- engine/src/components/particlerender.cpp | 6 +- engine/src/components/skinnedmeshrender.cpp | 6 +- engine/src/components/spriterender.cpp | 38 ++- engine/src/components/textrender.cpp | 11 +- engine/src/components/tilemaprender.cpp | 6 +- .../src/editor/converters/assimpconverter.cpp | 2 +- engine/src/editor/viewport/viewport.cpp | 14 +- engine/src/gizmos.cpp | 6 +- engine/src/pipelinecontext.cpp | 2 +- engine/src/pipelinetasks/ambientocclusion.cpp | 6 +- engine/src/pipelinetasks/antialiasing.cpp | 2 +- engine/src/pipelinetasks/bloom.cpp | 6 +- engine/src/pipelinetasks/deferredlighting.cpp | 2 +- engine/src/pipelinetasks/reflections.cpp | 4 +- engine/src/resources/material.cpp | 27 +- .../editor/graph/graphwidgets/linksrender.cpp | 37 +-- .../editor/graph/graphwidgets/linksrender.h | 4 +- .../editor/shadertools/converter/rootnode.h | 17 +- .../shadertools/converter/shaderbuilder.cpp | 293 ++++++++++++------ .../shadertools/converter/shaderbuilder.h | 22 +- .../shadertools/converter/shadernodegraph.cpp | 80 ++--- .../shadertools/converter/shadernodegraph.h | 2 +- .../shadertools/editor/materialedit.cpp | 5 +- .../editor/shadertools/shaders/Billboard.vert | 27 +- .../editor/shadertools/shaders/Shader.frag | 36 ++- .../editor/shadertools/shaders/ShaderLayout.h | 4 +- .../editor/shadertools/shaders/Skinned.vert | 27 +- .../editor/shadertools/shaders/Static.vert | 24 +- .../shadertools/shaders/VertexFactory.h | 12 - modules/editor/shadertools/shadertools.qrc | 1 - .../rendergl/includes/commandbuffergl.h | 6 +- .../rendergl/includes/resources/materialgl.h | 7 +- .../renders/rendergl/src/commandbuffergl.cpp | 36 +-- .../rendergl/src/resources/materialgl.cpp | 40 +-- modules/uikit/src/components/frame.cpp | 5 +- modules/uikit/src/components/image.cpp | 8 +- modules/uikit/src/components/label.cpp | 16 +- worldeditor/bin/editor/materials/debug.shader | 15 +- worldeditor/bin/editor/materials/grid.shader | 24 +- .../bin/engine/materials/AreaLight.shader | 5 +- .../bin/engine/materials/DefaultFont.shader | 35 +-- .../bin/engine/materials/DefaultMesh.mtl | 20 -- .../bin/engine/materials/DefaultMesh.shader | 37 +++ ...ultMesh.mtl.set => DefaultMesh.shader.set} | 0 .../bin/engine/materials/DefaultSprite.shader | 7 +- .../bin/engine/materials/DirectLight.shader | 7 +- worldeditor/bin/engine/materials/Frame.shader | 32 +- worldeditor/bin/engine/materials/Line.shader | 24 -- .../bin/engine/materials/Line.shader.set | 11 - worldeditor/bin/engine/materials/Link.shader | 32 +- 56 files changed, 596 insertions(+), 564 deletions(-) delete mode 100644 modules/editor/shadertools/shaders/VertexFactory.h delete mode 100644 worldeditor/bin/engine/materials/DefaultMesh.mtl create mode 100644 worldeditor/bin/engine/materials/DefaultMesh.shader rename worldeditor/bin/engine/materials/{DefaultMesh.mtl.set => DefaultMesh.shader.set} (100%) delete mode 100644 worldeditor/bin/engine/materials/Line.shader delete mode 100644 worldeditor/bin/engine/materials/Line.shader.set diff --git a/engine/includes/commandbuffer.h b/engine/includes/commandbuffer.h index a497dfe5b..a2c40117b 100644 --- a/engine/includes/commandbuffer.h +++ b/engine/includes/commandbuffer.h @@ -34,16 +34,6 @@ struct Global { float padding[13]; }; -struct Local { - Matrix4 model; - - Vector4 color; - - Vector4 objectId; - - Vector4 materialId; -}; - class ENGINE_EXPORT CommandBuffer: public Object { A_REGISTER(CommandBuffer, Object, System) @@ -64,18 +54,12 @@ class ENGINE_EXPORT CommandBuffer: public Object { virtual void dispatchCompute(ComputeInstance *shader, int32_t groupsX, int32_t groupsY, int32_t groupsZ); - virtual void drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *instance = nullptr); + virtual void drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance); - virtual void drawMeshInstanced(const Matrix4 *transform, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *instance = nullptr); + virtual void drawMeshInstanced(const Matrix4 *transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance, uint32_t count); virtual void setRenderTarget(RenderTarget *target, uint32_t level = 0); - virtual void setColor(const Vector4 &color); - - virtual void setObjectId(uint32_t id); - - virtual void setMaterialId(uint32_t id); - virtual void setScreenProjection(float x = -0.5f, float y = -0.5f, float width = 0.5f, float height = 0.5f); virtual void resetViewProjection(); @@ -113,7 +97,6 @@ class ENGINE_EXPORT CommandBuffer: public Object { bool m_screenProjection; Global m_global; - Local m_local; Matrix4 m_saveView; Matrix4 m_saveProjection; diff --git a/engine/includes/components/renderable.h b/engine/includes/components/renderable.h index 975d74bc4..2a156943a 100644 --- a/engine/includes/components/renderable.h +++ b/engine/includes/components/renderable.h @@ -37,7 +37,7 @@ class ENGINE_EXPORT Renderable : public NativeBehaviour { void loadUserData(const VariantMap &data) override; VariantMap saveUserData() const override; - void setMaterialsList(const list &materials); + virtual void setMaterialsList(const list &materials); private: void setSystem(ObjectSystem *system) override; diff --git a/engine/includes/components/spriterender.h b/engine/includes/components/spriterender.h index 9543fd720..8c4eb98be 100644 --- a/engine/includes/components/spriterender.h +++ b/engine/includes/components/spriterender.h @@ -69,6 +69,8 @@ class ENGINE_EXPORT SpriteRender : public Renderable { private: void draw(CommandBuffer &buffer, uint32_t layer) override; + void setMaterialsList(const list &materials) override; + AABBox localBound() const override; void loadUserData(const VariantMap &data) override; diff --git a/engine/includes/resources/material.h b/engine/includes/resources/material.h index 14919ace5..51b0980ab 100644 --- a/engine/includes/resources/material.h +++ b/engine/includes/resources/material.h @@ -48,9 +48,7 @@ class ENGINE_EXPORT Material : public Resource { enum SurfaceType { Static, Skinned, - Billboard, - Oriented, - Fullscreen + Billboard }; enum BlendOp { @@ -281,6 +279,7 @@ class ENGINE_EXPORT MaterialInstance { void setVector3(const char *name, const Vector3 *value, int32_t count = 1); void setVector4(const char *name, const Vector4 *value, int32_t count = 1); + void setTransform(const Matrix4 &tranform); void setMatrix4(const char *name, const Matrix4 *value, int32_t count = 1); virtual void setTexture(const char *name, Texture *texture); @@ -301,9 +300,9 @@ class ENGINE_EXPORT MaterialInstance { map m_textureOverride; map m_paramOverride; - Material *m_material; + vector m_uniformBuffer; - uint8_t *m_uniformBuffer; + Material *m_material; uint16_t m_surfaceType; diff --git a/engine/src/commandbuffer.cpp b/engine/src/commandbuffer.cpp index b3f818f50..f183dea3d 100644 --- a/engine/src/commandbuffer.cpp +++ b/engine/src/commandbuffer.cpp @@ -45,7 +45,7 @@ void CommandBuffer::dispatchCompute(ComputeInstance *shader, int32_t groupsX, in /*! Draws a \a mesh with the specified \a sub mesh index in the \a transform location with assigned material \a instance, and rendering \a layer. */ -void CommandBuffer::drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) { +void CommandBuffer::drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) { A_UNUSED(transform); A_UNUSED(mesh); A_UNUSED(sub); @@ -57,13 +57,13 @@ void CommandBuffer::drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, GPU will draw this mesh with the specified \a sub mesh index in different \a transform locations with assigned material \a instance, and rendering \a layer. Parameter \a count specifies the number of instances to draw. */ -void CommandBuffer::drawMeshInstanced(const Matrix4 *transform, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) { +void CommandBuffer::drawMeshInstanced(const Matrix4 *transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance, uint32_t count) { A_UNUSED(transform); - A_UNUSED(count); A_UNUSED(mesh); A_UNUSED(sub); A_UNUSED(layer); A_UNUSED(instance); + A_UNUSED(count); } /*! Sets the render \a target for subsequent rendering commands. @@ -97,24 +97,6 @@ bool CommandBuffer::isInited() { void CommandBuffer::setInited() { s_Inited = true; } -/*! - Sets the \a color for rendering commands. -*/ -void CommandBuffer::setColor(const Vector4 &color) { - m_local.color = color; -} -/*! - Sets the object \a id for rendering commands. -*/ -void CommandBuffer::setObjectId(uint32_t id) { - m_local.objectId = idToColor(id); -} -/*! - Sets the material \a id for rendering commands. -*/ -void CommandBuffer::setMaterialId(uint32_t id) { - m_local.materialId = idToColor(id); -} /*! Sets the screen projection matrix. Parameters \a x and \a y represents screen coordinates. diff --git a/engine/src/components/meshrender.cpp b/engine/src/components/meshrender.cpp index ccbe253f0..3b5e64b94 100644 --- a/engine/src/components/meshrender.cpp +++ b/engine/src/components/meshrender.cpp @@ -34,16 +34,12 @@ void MeshRender::draw(CommandBuffer &buffer, uint32_t layer) { if(m_mesh && !m_materials.empty() && layer & a->layers()) { Transform *t = a->transform(); if(t) { - buffer.setObjectId(a->uuid()); - buffer.setColor(Vector4(1.0f)); - const Matrix4 &transform = t->worldTransform(); for(int i = 0; i < m_mesh->subMeshCount(); i++) { MaterialInstance *instance = (i < m_materials.size()) ? m_materials[i] : nullptr; if(instance) { - buffer.setMaterialId(instance->material()->uuid()); - buffer.drawMesh(transform, m_mesh, i, layer, instance); + buffer.drawMesh(transform, m_mesh, i, layer, *instance); } } } diff --git a/engine/src/components/particlerender.cpp b/engine/src/components/particlerender.cpp index 4c526bb6e..989fd0bda 100644 --- a/engine/src/components/particlerender.cpp +++ b/engine/src/components/particlerender.cpp @@ -136,16 +136,12 @@ void ParticleRender::deltaUpdate(float dt) { void ParticleRender::draw(CommandBuffer &buffer, uint32_t layer) { Actor *a = actor(); if(layer & a->layers()) { - buffer.setObjectId(a->uuid()); - for(uint32_t index = 0; index < m_buffers.size(); index++) { MaterialInstance *instance = m_materials[index]; if(m_visibleCount[index] > 0 && instance) { - buffer.setMaterialId(instance->material()->uuid()); - ParticleEmitter *emitter = m_effect->emitter(index); Matrix4 *transforms = m_buffers[index].data(); - buffer.drawMeshInstanced(transforms, m_visibleCount[index], emitter->mesh(), 0, layer, instance); + buffer.drawMeshInstanced(transforms, emitter->mesh(), 0, layer, *instance, m_visibleCount[index]); } } } diff --git a/engine/src/components/skinnedmeshrender.cpp b/engine/src/components/skinnedmeshrender.cpp index f5b362581..2c893ac50 100644 --- a/engine/src/components/skinnedmeshrender.cpp +++ b/engine/src/components/skinnedmeshrender.cpp @@ -39,16 +39,12 @@ void SkinnedMeshRender::draw(CommandBuffer &buffer, uint32_t layer) { if(m_mesh && !m_materials.empty() && layer & a->layers()) { Transform *t = a->transform(); if(t) { - buffer.setObjectId(a->uuid()); - buffer.setColor(Vector4(1.0f)); - const Matrix4 &transform = t->worldTransform(); for(int i = 0; i < m_mesh->subMeshCount(); i++) { MaterialInstance *instance = (i < m_materials.size()) ? m_materials[i] : nullptr; if(instance) { - buffer.setMaterialId(instance->material()->uuid()); - buffer.drawMesh(transform, m_mesh, i, layer, instance); + buffer.drawMesh(transform, m_mesh, i, layer, *instance); } } } diff --git a/engine/src/components/spriterender.cpp b/engine/src/components/spriterender.cpp index ddb54c67a..187f82637 100644 --- a/engine/src/components/spriterender.cpp +++ b/engine/src/components/spriterender.cpp @@ -13,7 +13,9 @@ namespace { const char *gBaseMap = "BaseMap"; - const char *gOverride = "mainTexture"; + + const char *gColor = "mainColor"; + const char *gTexture = "mainTexture"; const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; } @@ -66,11 +68,7 @@ void SpriteRender::draw(CommandBuffer &buffer, uint32_t layer) { Transform *t = a->transform(); if(t) { - buffer.setObjectId(a->uuid()); - buffer.setColor(m_color); - buffer.setMaterialId(material()->uuid()); - - buffer.drawMesh(t->worldTransform(), (m_customMesh) ? m_customMesh : m_mesh, 0, layer, m_materials.front()); + buffer.drawMesh(t->worldTransform(), (m_customMesh) ? m_customMesh : m_mesh, 0, layer, *m_materials.front()); } } } @@ -106,7 +104,7 @@ void SpriteRender::setSprite(Sprite *sheet) { composeMesh(); if(!m_materials.empty()) { - m_materials[0]->setTexture(gOverride, m_sheet->page()); + m_materials[0]->setTexture(gTexture, m_sheet->page()); } } } @@ -137,7 +135,7 @@ void SpriteRender::setTexture(Texture *texture) { } composeMesh(); - m_materials[0]->setTexture(gOverride, m_texture); + m_materials[0]->setTexture(gTexture, m_texture); } } /*! @@ -151,6 +149,10 @@ Vector4 SpriteRender::color() const { */ void SpriteRender::setColor(const Vector4 color) { m_color = color; + + for(auto it : m_materials) { + it->setVector4(gColor, &m_color); + } } /*! Returns the current item name of sprite from the sprite sheet. @@ -237,8 +239,20 @@ VariantMap SpriteRender::saveUserData() const { void SpriteRender::setMaterial(Material *material) { Renderable::setMaterial(material); - if(!m_materials.empty()) { - m_materials[0]->setTexture(gOverride, texture()); + for(auto it : m_materials) { + it->setTexture(gTexture, texture()); + it->setVector4(gColor, &m_color); + } +} +/*! + \internal +*/ +void SpriteRender::setMaterialsList(const list &materials) { + Renderable::setMaterialsList(materials); + + for(auto it : m_materials) { + it->setTexture(gTexture, texture()); + it->setVector4(gColor, &m_color); } } /*! @@ -467,14 +481,14 @@ void SpriteRender::spriteUpdated(int state, void *ptr) { switch(state) { case Resource::Ready: { if(!p->m_materials.empty()) { - p->m_materials[0]->setTexture(gOverride, p->m_sheet->page()); + p->m_materials[0]->setTexture(gTexture, p->m_sheet->page()); } p->composeMesh(); } break; case Resource::ToBeDeleted: { p->m_sheet = nullptr; if(!p->m_materials.empty()) { - p->m_materials[0]->setTexture(gOverride, nullptr); + p->m_materials[0]->setTexture(gTexture, nullptr); } p->composeMesh(); } break; diff --git a/engine/src/components/textrender.cpp b/engine/src/components/textrender.cpp index b7781159c..944d5294e 100644 --- a/engine/src/components/textrender.cpp +++ b/engine/src/components/textrender.cpp @@ -14,7 +14,7 @@ namespace { const char *gFont = "Font"; - const char *gOverride = "texture0"; + const char *gOverride = "mainTexture"; }; /*! @@ -59,11 +59,7 @@ void TextRender::draw(CommandBuffer &buffer, uint32_t layer) { if(m_mesh && !m_materials.empty() && layer & a->layers() && !m_text.empty()) { Transform *t = a->transform(); if(t) { - buffer.setObjectId(a->uuid()); - buffer.setMaterialId(material()->uuid()); - buffer.setColor(m_color); - - buffer.drawMesh(t->worldTransform(), m_mesh, 0, layer, m_materials.front()); + buffer.drawMesh(t->worldTransform(), m_mesh, 0, layer, *m_materials.front()); } } } @@ -140,6 +136,9 @@ Vector4 TextRender::color() const { */ void TextRender::setColor(const Vector4 color) { m_color = color; + for(auto it : m_materials) { + it->setVector4("mainColor", &m_color); + } } /*! Returns true if word wrap enabled; otherwise returns false. diff --git a/engine/src/components/tilemaprender.cpp b/engine/src/components/tilemaprender.cpp index 542738d2e..0d041af4e 100644 --- a/engine/src/components/tilemaprender.cpp +++ b/engine/src/components/tilemaprender.cpp @@ -47,11 +47,7 @@ void TileMapRender::draw(CommandBuffer &buffer, uint32_t layer) { if(m_tileMap && !m_materials.empty() && layer & a->layers()) { Transform *t = a->transform(); if(t) { - buffer.setObjectId(a->uuid()); - buffer.setColor(Vector4(1.0f)); - - buffer.setMaterialId(material()->uuid()); - buffer.drawMesh(t->worldTransform(), m_tileMap->tileMesh(), 0, layer, m_materials.front()); + buffer.drawMesh(t->worldTransform(), m_tileMap->tileMesh(), 0, layer, *m_materials.front()); } } } diff --git a/engine/src/editor/converters/assimpconverter.cpp b/engine/src/editor/converters/assimpconverter.cpp index 0fab18b6b..1c6ac8d8b 100644 --- a/engine/src/editor/converters/assimpconverter.cpp +++ b/engine/src/editor/converters/assimpconverter.cpp @@ -497,7 +497,7 @@ Mesh *AssimpConverter::importMesh(const aiScene *scene, const aiNode *element, A } mesh->setSubMesh(total_i, index); - mesh->setDefaultMaterial(Engine::loadResource(".embedded/DefaultMesh.mtl"), index); + mesh->setDefaultMaterial(Engine::loadResource(".embedded/DefaultMesh.shader"), index); total_v += vertexCount; total_i += indexCount; diff --git a/engine/src/editor/viewport/viewport.cpp b/engine/src/editor/viewport/viewport.cpp index fdd96c9ed..4aae5bdff 100644 --- a/engine/src/editor/viewport/viewport.cpp +++ b/engine/src/editor/viewport/viewport.cpp @@ -113,7 +113,7 @@ class Outline : public PipelineTask { context.drawRenderers(filter, CommandBuffer::RAYCAST); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_combineMaterial); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combineMaterial); buffer->endDebugMarker(); } @@ -172,6 +172,9 @@ class GridRender : public PipelineTask { void loadSettings() { QColor color = EditorSettings::instance()->value(gGridColor, QColor(102, 102, 102, 102)).value(); m_gridColor = Vector4(color.redF(), color.greenF(), color.blueF(), color.alphaF()); + if(m_grid) { + m_grid->setVector4("mainColor", &m_gridColor); + } } float scale() const { @@ -269,15 +272,14 @@ class GridRender : public PipelineTask { m_grid->setBool("ortho", &ortho); m_grid->setFloat("scale", &m_scale); m_grid->setFloat("width", &width); + m_grid->setVector4("gridColor", &m_gridColor); CommandBuffer *buffer = context.buffer(); buffer->beginDebugMarker("GridRender"); buffer->setRenderTarget(m_resultTarget); - buffer->setColor(m_gridColor); - buffer->drawMesh(Matrix4(pos, rot, m_scale), m_plane, 0, CommandBuffer::TRANSLUCENT, m_grid); - buffer->setColor(Vector4(1.0f)); + buffer->drawMesh(Matrix4(pos, rot, m_scale), m_plane, 0, CommandBuffer::TRANSLUCENT, *m_grid); buffer->endDebugMarker(); } @@ -345,8 +347,6 @@ class GizmoRender : public PipelineTask { if(cam) { buffer->setViewProjection(cam->viewMatrix(), cam->projectionMatrix()); } - buffer->setColor(Vector4(1.0f)); - buffer->setRenderTarget(m_spriteTarget); Gizmos::drawSpriteBatch(buffer); @@ -416,7 +416,7 @@ class DebugRender : public PipelineTask { m.mat[12] = width * 0.5f + (i - 4) * width - 1.0f; m.mat[13] = 1.0f - height * 0.5f; } - buffer->drawMesh(m, m_mesh, 0, CommandBuffer::UI, it.second); + buffer->drawMesh(m, m_mesh, 0, CommandBuffer::UI, *it.second); i++; } diff --git a/engine/src/gizmos.cpp b/engine/src/gizmos.cpp index 4f515f0b3..0989ad9c7 100644 --- a/engine/src/gizmos.cpp +++ b/engine/src/gizmos.cpp @@ -83,7 +83,7 @@ void Gizmos::clear() { void Gizmos::drawSpriteBatch(CommandBuffer *buffer) { for(auto &it : s_sprites) { if(!it.second.mesh->isEmpty()) { - buffer->drawMesh(Matrix4(), it.second.mesh, 0, CommandBuffer::TRANSLUCENT, it.second.material); + buffer->drawMesh(Matrix4(), it.second.mesh, 0, CommandBuffer::TRANSLUCENT, *it.second.material); } } } @@ -93,7 +93,7 @@ void Gizmos::drawSpriteBatch(CommandBuffer *buffer) { */ void Gizmos::drawSolidBatch(CommandBuffer *buffer) { if(!s_solid->isEmpty()) { - buffer->drawMesh(Matrix4(), s_solid, 0, CommandBuffer::TRANSLUCENT, s_solidMaterial); + buffer->drawMesh(Matrix4(), s_solid, 0, CommandBuffer::TRANSLUCENT, *s_solidMaterial); } } /*! @@ -102,7 +102,7 @@ void Gizmos::drawSolidBatch(CommandBuffer *buffer) { */ void Gizmos::drawWireBatch(CommandBuffer *buffer) { if(!s_wire->isEmpty()) { - buffer->drawMesh(Matrix4(), s_wire, 0, CommandBuffer::TRANSLUCENT, s_wireMaterial); + buffer->drawMesh(Matrix4(), s_wire, 0, CommandBuffer::TRANSLUCENT, *s_wireMaterial); } } /*! diff --git a/engine/src/pipelinecontext.cpp b/engine/src/pipelinecontext.cpp index fe2e51d1e..45399eb69 100644 --- a/engine/src/pipelinecontext.cpp +++ b/engine/src/pipelinecontext.cpp @@ -97,7 +97,7 @@ void PipelineContext::draw(Camera *camera) { // Finish m_buffer->setRenderTarget(m_defaultTarget); m_buffer->clearRenderTarget(); - m_buffer->drawMesh(Matrix4(), defaultPlane(), 0, CommandBuffer::UI, m_finalMaterial); + m_buffer->drawMesh(Matrix4(), defaultPlane(), 0, CommandBuffer::UI, *m_finalMaterial); } /*! Sets the current \a camera and updates associated matrices in the command buffer. diff --git a/engine/src/pipelinetasks/ambientocclusion.cpp b/engine/src/pipelinetasks/ambientocclusion.cpp index db72c3453..1f81f42a2 100644 --- a/engine/src/pipelinetasks/ambientocclusion.cpp +++ b/engine/src/pipelinetasks/ambientocclusion.cpp @@ -129,14 +129,14 @@ void AmbientOcclusion::exec(PipelineContext &context) { buffer->setViewport(0, 0, m_outputs.front().second->width(), m_outputs.front().second->height()); buffer->setRenderTarget(m_ssaoTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_occlusion); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_occlusion); } if(m_blur) { buffer->setViewport(0, 0, m_outputs.back().second->width(), m_outputs.back().second->height()); buffer->setRenderTarget(m_blurTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_blur); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_blur); } if(m_combine) { @@ -146,7 +146,7 @@ void AmbientOcclusion::exec(PipelineContext &context) { } buffer->setRenderTarget(m_combineTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_combine); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combine); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/antialiasing.cpp b/engine/src/pipelinetasks/antialiasing.cpp index 26df476f6..181d65305 100644 --- a/engine/src/pipelinetasks/antialiasing.cpp +++ b/engine/src/pipelinetasks/antialiasing.cpp @@ -44,7 +44,7 @@ void AntiAliasing::exec(PipelineContext &context) { buffer->beginDebugMarker("AntiAliasing"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_material); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_material); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/bloom.cpp b/engine/src/pipelinetasks/bloom.cpp index 25e5e9485..7002c548d 100644 --- a/engine/src/pipelinetasks/bloom.cpp +++ b/engine/src/pipelinetasks/bloom.cpp @@ -106,7 +106,7 @@ void Bloom::exec(PipelineContext &context) { buffer->setRenderTarget(m_bloomPasses[i].downTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_bloomPasses[i].downMaterial); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].downMaterial); } buffer->setViewport(0, 0, texture->width(), texture->height()); @@ -118,10 +118,10 @@ void Bloom::exec(PipelineContext &context) { for(uint8_t i = 0; i < BLOOM_PASSES; i++) { buffer->setRenderTarget(m_blurTempTarget); buffer->clearRenderTarget(true, Vector4(0.0f), false, 1.0f); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_bloomPasses[i].blurMaterialH); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialH); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_bloomPasses[i].blurMaterialV); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialV); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/deferredlighting.cpp b/engine/src/pipelinetasks/deferredlighting.cpp index 8a06d6a12..56a49c0d4 100644 --- a/engine/src/pipelinetasks/deferredlighting.cpp +++ b/engine/src/pipelinetasks/deferredlighting.cpp @@ -111,7 +111,7 @@ void DeferredLighting::exec(PipelineContext &context) { default: break; } - buffer->drawMesh(mat, mesh, 0, CommandBuffer::LIGHT, light->material()); + buffer->drawMesh(mat, mesh, 0, CommandBuffer::LIGHT, *light->material()); } buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/reflections.cpp b/engine/src/pipelinetasks/reflections.cpp index 7a36bdbdb..1b185a1ae 100644 --- a/engine/src/pipelinetasks/reflections.cpp +++ b/engine/src/pipelinetasks/reflections.cpp @@ -61,13 +61,13 @@ void Reflections::exec(PipelineContext &context) { if(m_slrMaterial) { // sslr step buffer->setRenderTarget(m_slrTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_slrMaterial); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_slrMaterial); } if(m_combineMaterial) { // combine step buffer->setRenderTarget(m_combineTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, m_combineMaterial); + buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combineMaterial); } buffer->endDebugMarker(); diff --git a/engine/src/resources/material.cpp b/engine/src/resources/material.cpp index e8d5856ec..4ed0add97 100644 --- a/engine/src/resources/material.cpp +++ b/engine/src/resources/material.cpp @@ -24,17 +24,13 @@ namespace { MaterialInstance::MaterialInstance(Material *material) : m_material(material), - m_uniformBuffer(nullptr), m_surfaceType(0), m_uniformDirty(true) { - if(m_material->m_uniformSize > 0) { - m_uniformBuffer = new uint8_t[m_material->m_uniformSize]; - } } MaterialInstance::~MaterialInstance() { - delete []m_uniformBuffer; + } /*! Getter for the base material associated with the instance. @@ -166,6 +162,16 @@ void MaterialInstance::setVector4(const char *name, const Vector4 *value, int32_ setBufferValue(name, value); } +/*! + Sets the \a transform matrix for the object. +*/ +void MaterialInstance::setTransform(const Matrix4 &tranform) { + if(m_uniformBuffer.size() < m_material->m_uniformSize) { + m_uniformBuffer.resize(m_material->m_uniformSize); + } + memcpy(m_uniformBuffer.data(), &tranform, sizeof(Matrix4)); + m_uniformDirty = true; +} /*! Sets a Matrix4 parameter with optional array support. Parameter \a name specifies a name of the Matrix4 parameter. @@ -191,10 +197,11 @@ void MaterialInstance::setMatrix4(const char *name, const Matrix4 *value, int32_ void MaterialInstance::setBufferValue(const char *name, const void *value) { for(auto &it : m_material->m_uniforms) { if(it.name == name) { - if(m_uniformBuffer) { - memcpy(&m_uniformBuffer[it.offset], value, it.size); - m_uniformDirty = true; + if(m_uniformBuffer.size() < m_material->m_uniformSize) { + m_uniformBuffer.resize(m_material->m_uniformSize); } + memcpy(&m_uniformBuffer[it.offset], value, it.size); + m_uniformDirty = true; break; } } @@ -389,11 +396,11 @@ void Material::loadUserData(const VariantMap &data) { } } { - m_uniformSize = 0; + m_uniformSize = sizeof(Matrix4); m_uniforms.clear(); auto it = data.find(gUniforms); if(it != data.end()) { - size_t offset = 0; + size_t offset = m_uniformSize; VariantList uniforms = (*it).second.toList(); m_uniforms.resize(uniforms.size()); int i = 0; diff --git a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp index 924a090ba..a87cafdf1 100644 --- a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp +++ b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp @@ -13,26 +13,19 @@ #include #include -namespace { - const char *gColor = "color0"; -}; - LinksRender::LinksRender() : m_graph(nullptr), - m_linksMesh(Engine::objectCreate("")), - m_creationMesh(Engine::objectCreate("")), + m_linksMesh(Engine::objectCreate("LinkMesh")), + m_creationMesh(Engine::objectCreate("CreationLink")), m_material(nullptr), m_portWidget(nullptr) { m_linksMesh->makeDynamic(); m_creationMesh->makeDynamic(); - Material *m = dynamic_cast(Engine::loadResource(".embedded/Line.shader")); + Material *m = dynamic_cast(Engine::loadResource(".embedded/Link.shader")); if(m) { m_material = m->createInstance(); - - Vector4 color(1.0f); - m_material->setVector4(gColor, &color); } } @@ -45,11 +38,12 @@ void LinksRender::setGraph(AbstractNodeGraph *graph) { void LinksRender::draw(CommandBuffer &buffer) { if(m_linksMesh && !m_linksMesh->vertices().empty()) { buffer.drawMesh(rectTransform()->worldTransform(), - m_linksMesh, 0, CommandBuffer::UI, m_material); + m_linksMesh, 0, CommandBuffer::UI, *m_material); } if(m_creationMesh && m_portWidget) { Vector3Vector vertices; Vector2Vector uvs; + Vector4Vector colors; IndexVector indices; Vector3 pos = GraphController::worldPosition(); @@ -65,14 +59,14 @@ void LinksRender::draw(CommandBuffer &buffer) { } else { s = Vector3(pos.x, pos.y, 0.0f); } - composeBezierLink(s, e, vertices, uvs, indices); + composeBezierLink(s, e, vertices, uvs, colors, indices); } else { RectTransform *rect = m_portWidget->rectTransform(); s = rect->worldTransform() * Vector3(rect->size() * 0.5f, 0.0f); e = Vector3(pos.x, pos.y, 0.0f); - composeStateLink(s, e, vertices, uvs, indices); + composeStateLink(s, e, vertices, uvs, colors, indices); } if(!vertices.empty()) { @@ -83,7 +77,7 @@ void LinksRender::draw(CommandBuffer &buffer) { } buffer.drawMesh(rectTransform()->worldTransform(), - m_creationMesh, 0, CommandBuffer::UI, m_material); + m_creationMesh, 0, CommandBuffer::UI, *m_material); } } @@ -98,6 +92,7 @@ void LinksRender::setCreationLink(Widget *widget) { void LinksRender::composeLinks() { Vector3Vector vertices; Vector2Vector uvs; + Vector4Vector colors; IndexVector indices; uint32_t link = 0; @@ -147,16 +142,18 @@ void LinksRender::composeLinks() { Vector3Vector localVertices; Vector2Vector localUvs; + Vector4Vector localColors; IndexVector localIndices; if(!state) { - composeBezierLink(s, e, localVertices, localUvs, localIndices, link); + composeBezierLink(s, e, localVertices, localUvs, localColors, localIndices, link); } else { - composeStateLink(s, e, localVertices, localUvs, localIndices, link); + composeStateLink(s, e, localVertices, localUvs, localColors, localIndices, link); } vertices.insert(vertices.end(), localVertices.begin(), localVertices.end()); uvs.insert(uvs.end(), localUvs.begin(), localUvs.end()); + colors.insert(colors.end(), localColors.begin(), localColors.end()); indices.insert(indices.end(), localIndices.begin(), localIndices.end()); ++link; @@ -165,6 +162,7 @@ void LinksRender::composeLinks() { if(!vertices.empty()) { m_linksMesh->setVertices(vertices); m_linksMesh->setUv0(uvs); + m_linksMesh->setColors(colors); m_linksMesh->setIndices(indices); m_linksMesh->recalcBounds(); } else { @@ -172,13 +170,14 @@ void LinksRender::composeLinks() { } } -void LinksRender::composeBezierLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, IndexVector &indices, int32_t link) { +void LinksRender::composeBezierLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, Vector4Vector &colors, IndexVector &indices, int32_t link) { const int32_t steps = 20; Vector3Vector points = Mathf::pointsCurve(s, e, Vector3(s.x + 40.0f, s.y, s.z), Vector3(e.x - 40.0f, e.y, e.z), steps); vertices.resize(steps * 2); uvs.resize(steps * 2); + colors = Vector4Vector(steps * 2, Vector4(1.0f)); indices.resize(steps * 6); Vector3 ortho; @@ -207,7 +206,7 @@ void LinksRender::composeBezierLink(Vector3 &s, Vector3 &e, Vector3Vector &verti } } -void LinksRender::composeStateLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, IndexVector &indices, int32_t link) { +void LinksRender::composeStateLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, Vector4Vector &colors, IndexVector &indices, int32_t link) { Vector3 delta = e - s; delta.normalize(); Vector3 o1 = delta.cross(Vector3(0.0f, 0.0f, 2.0f)); @@ -223,6 +222,8 @@ void LinksRender::composeStateLink(Vector3 &s, Vector3 &e, Vector3Vector &vertic uvs = { Vector2(0.0f, 0.0f), Vector2(1.0f, 0.0f), Vector2(0.0f, 1.0f), Vector2(1.0f, 1.0f), Vector2(1.0f, 1.0f), Vector2(1.0f, 1.0f), Vector2(1.0f, 1.0f) }; + colors = Vector4Vector(7, Vector4(1.0f)); + uint32_t index = link * 7; indices = { index + 0, index + 1, index + 2, diff --git a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.h b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.h index 460506e4c..58c29d5a4 100644 --- a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.h +++ b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.h @@ -25,8 +25,8 @@ class LinksRender : public Widget { private: void draw(CommandBuffer &buffer) override; - void composeBezierLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, IndexVector &indices, int32_t link = 0); - void composeStateLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, IndexVector &indices, int32_t link = 0); + void composeBezierLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, Vector4Vector &colors, IndexVector &indices, int32_t link = 0); + void composeStateLink(Vector3 &s, Vector3 &e, Vector3Vector &vertices, Vector2Vector &uvs, Vector4Vector &colors, IndexVector &indices, int32_t link = 0); bool intersects2D(const Vector3 &a1, const Vector3 &a2, const Vector3 &b1, const Vector3 &b2, Vector3 &intersection); diff --git a/modules/editor/shadertools/converter/rootnode.h b/modules/editor/shadertools/converter/rootnode.h index b0a75f2db..953b68105 100644 --- a/modules/editor/shadertools/converter/rootnode.h +++ b/modules/editor/shadertools/converter/rootnode.h @@ -14,6 +14,9 @@ class ShaderRootNode : public GraphNode { Q_PROPERTY(bool wireFrame READ isWireframe WRITE setWireframe NOTIFY graphUpdated DESIGNABLE true USER true) Q_PROPERTY(bool twoSided READ isDoubleSided WRITE setDoubleSided NOTIFY graphUpdated DESIGNABLE true USER true) + Q_PROPERTY(bool useWithSkinned READ useWithSkinned WRITE setUseWithSkinned NOTIFY graphUpdated DESIGNABLE true USER true) + Q_PROPERTY(bool useWithParticles READ useWithParticles WRITE setUseWithParticles NOTIFY graphUpdated DESIGNABLE true USER true) + Q_PROPERTY(BlendOp blendColorOperation READ blendColorOperation WRITE setBlendColorOperation NOTIFY graphUpdated DESIGNABLE true USER true) Q_PROPERTY(BlendOp blendAlphaOperation READ blendAlphaOperation WRITE setBlendAlphaOperation NOTIFY graphUpdated DESIGNABLE true USER true) Q_PROPERTY(BlendFactor blendSourceColor READ blendSourceColor WRITE setBlendSourceColor NOTIFY graphUpdated DESIGNABLE true USER true) @@ -116,7 +119,9 @@ class ShaderRootNode : public GraphNode { m_lightModel(Lit), m_materialType(Surface), m_doubleSided(false), - m_wireframe(false) { + m_wireframe(false), + m_useWithSkinned(true), + m_useWithParticles(true) { } @@ -132,6 +137,12 @@ class ShaderRootNode : public GraphNode { LightModel lightModel() const { return m_lightModel; } void setLightModel(LightModel model) { m_lightModel = model; emit graphUpdated(); } + bool useWithSkinned() const { return m_useWithSkinned; } + void setUseWithSkinned(bool use) { m_useWithSkinned = use; emit graphUpdated(); } + + bool useWithParticles() const { return m_useWithParticles; } + void setUseWithParticles(bool use) { m_useWithParticles = use; emit graphUpdated(); } + BlendOp blendAlphaOperation() const { return static_cast(m_blendState.alphaOperation); } void setBlendAlphaOperation(BlendOp operation) { m_blendState.alphaOperation = operation; emit graphUpdated(); } @@ -225,6 +236,10 @@ class ShaderRootNode : public GraphNode { bool m_wireframe; + bool m_useWithSkinned; + + bool m_useWithParticles; + }; Q_DECLARE_METATYPE(Material::LightModel) diff --git a/modules/editor/shadertools/converter/shaderbuilder.cpp b/modules/editor/shadertools/converter/shaderbuilder.cpp index 27534ba75..c1c09fa3b 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.cpp +++ b/modules/editor/shadertools/converter/shaderbuilder.cpp @@ -129,6 +129,107 @@ ShaderBuilderSettings::Rhi ShaderBuilder::currentRhi() { return rhi; } +void ShaderBuilder::buildInstanceData(const VariantMap &user, PragmaMap &pragmas) { + string result; + + string modelMatrix = + " mat4 modelMatrix = mat4(instance.data[_instanceOffset + 0]," + " instance.data[_instanceOffset + 1]," + " instance.data[_instanceOffset + 2]," + " instance.data[_instanceOffset + 3]);\n"; + + int offset = 4; + + string uniforms; + auto it = user.find(UNIFORMS); + if(it != user.end()) { + int sub = 0; + const char *compNames = "xyzw"; + for(auto &p : it->second.toList()) { + Uniform uniform = uniformFromVariant(p); + + string comp; + + if(uniform.type == MetaType::MATRIX4) { + if(sub > 0) { + sub = 0; + offset++; + } + + } else { + string prefix; + + switch(uniform.type) { + case MetaType::BOOLEAN: { + prefix = "floatBitsToInt("; + comp = compNames[sub]; + comp += ") != 0"; + sub++; + } break; + case MetaType::INTEGER: { + prefix = "floatBitsToInt("; + comp = compNames[sub]; + comp += ")"; + sub++; + } break; + case MetaType::FLOAT: { + comp = compNames[sub]; + sub++; + } break; + case MetaType::VECTOR2: { + if(sub > 2) { + sub = 0; + offset++; + } + + comp = compNames[sub]; + sub++; + comp += compNames[sub]; + sub++; + } break; + case MetaType::VECTOR3: { + if(sub > 1) { + sub = 0; + offset++; + } + + comp = compNames[sub]; + sub++; + comp += compNames[sub]; + sub++; + comp += compNames[sub]; + sub++; + } break; + case MetaType::VECTOR4: { + comp = compNames; + sub = 4; + } break; + default: break; + } + + string data = prefix + "instance.data[_instanceOffset + " + to_string(offset) + "]." + comp + ";\n"; + + if(sub >= 4) { + sub = 0; + offset++; + } + + uniforms += uniform.typeName + " " + uniform.name + " = " + data; + } + } + + if(sub > 0) { + offset++; + } + } + + pragmas["offset"] = "_instanceOffset = gl_InstanceIndex * " + to_string(offset) + ";\n"; + result += modelMatrix; + result += uniforms; + + pragmas["instance"] = result; +} + Actor *ShaderBuilder::createActor(const AssetConverterSettings *settings, const QString &guid) const { Actor *object = Engine::composeActor("MeshRender", ""); @@ -180,11 +281,43 @@ AssetConverter::ReturnCode ShaderBuilder::convertFile(AssetConverterSettings *se return InternalError; } - uint32_t version = 430; - bool es = false; + compileData(data); + + VariantList object; + + object.push_back(Material::metaClass()->name()); // type + object.push_back(0); // id + object.push_back(0); // parent + object.push_back(builderSettings->destination().toStdString()); // name + + object.push_back(VariantMap()); // properties + + object.push_back(VariantList()); // links + object.push_back(data); // user data + + VariantList result; + result.push_back(object); + + QFile file(builderSettings->absoluteDestination()); + if(file.open(QIODevice::WriteOnly)) { + ByteArray data = Bson::save(result); + file.write(reinterpret_cast(data.data()), data.size()); + file.close(); + + builderSettings->setRhi(currentRhi()); + + return Success; + } + + return InternalError; +} +void ShaderBuilder::compileData(VariantMap &data) { ShaderBuilderSettings::Rhi rhi = currentRhi(); + uint32_t version = 430; + bool es = false; + if(ProjectSettings::instance()->currentPlatformName() != "desktop") { version = 300; es = true; @@ -226,47 +359,13 @@ AssetConverter::ReturnCode ShaderBuilder::convertFile(AssetConverterSettings *se data[SKINNED] = compile(rhi, it->second.toString(), inputs, EShLangVertex); } - it = data.find(FULLSCREEN); - if(it != data.end()) { - data[FULLSCREEN] = compile(rhi, it->second.toString(), inputs, EShLangVertex); - } - it = data.find(GEOMETRY); if(it != data.end()) { data[GEOMETRY] = compile(rhi, it->second.toString(), inputs, EShLangGeometry); } - - VariantList result; - - VariantList object; - - object.push_back(Material::metaClass()->name()); // type - object.push_back(0); // id - object.push_back(0); // parent - object.push_back(builderSettings->destination().toStdString()); // name - - object.push_back(VariantMap()); // properties - - object.push_back(VariantList()); // links - object.push_back(data); // user data - - result.push_back(object); - - QFile file(builderSettings->absoluteDestination()); - if(file.open(QIODevice::WriteOnly)) { - ByteArray data = Bson::save(result); - file.write(reinterpret_cast(data.data()), data.size()); - file.close(); - - builderSettings->setRhi(rhi); - - return Success; - } - - return InternalError; } -Variant ShaderBuilder::compile(ShaderBuilderSettings::Rhi rhi, const string &buff, SpirVConverter::Inputs &inputs, int stage) const { +Variant ShaderBuilder::compile(ShaderBuilderSettings::Rhi rhi, const string &buff, SpirVConverter::Inputs &inputs, int stage) { inputs.clear(); Variant data; @@ -299,6 +398,7 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo map shaders; int materialType = Material::Surface; + int lightingModel = Material::Unlit; QDomElement shader = doc.documentElement(); @@ -317,7 +417,7 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo return false; } } else if(element.tagName() == gPass) { - user[PROPERTIES] = parsePassProperties(element, materialType); + user[PROPERTIES] = parsePassProperties(element, materialType, lightingModel); if(version == 0) { parsePassV0(element, user); @@ -334,7 +434,8 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo } string define; - const PragmaMap pragmas; + PragmaMap pragmas; + buildInstanceData(user, pragmas); if(compute) { string str = shaders[gCompute]; @@ -343,7 +444,13 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo } } else { if(currentRhi() == ShaderBuilderSettings::Rhi::Vulkan) { - define += "\n#define VULKAN\n"; + define += "\n#define VULKAN"; + } + + define += "\n#define USE_GBUFFER"; + + if(lightingModel == Material::Lit) { + define += "\n#define USE_TBN"; } string str; @@ -376,6 +483,57 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo return true; } +Uniform ShaderBuilder::uniformFromVariant(const Variant &variant) { + Uniform uniform; + + VariantList fields = variant.toList(); + + auto field = fields.begin(); + Variant value = *field; + ++field; + uint32_t size = field->toInt(); + ++field; + uniform.name = field->toString(); + + uniform.type = value.userType(); + + switch(uniform.type) { + case MetaType::BOOLEAN: { + uniform.typeName = "bool"; + size /= sizeof(bool); + } break; + case MetaType::INTEGER: { + uniform.typeName = "int"; + size /= sizeof(int); + } break; + case MetaType::FLOAT: { + uniform.typeName = "float"; + size /= sizeof(float); + } break; + case MetaType::VECTOR2: { + uniform.typeName = "vec2"; + size /= sizeof(Vector2); + } break; + case MetaType::VECTOR3: { + uniform.typeName = "vec3"; + size /= sizeof(Vector3); + } break; + case MetaType::VECTOR4: { + uniform.typeName = "vec4"; + size /= sizeof(Vector4); + } break; + case MetaType::MATRIX4: { + uniform.typeName = "mat4"; + size /= sizeof(Matrix4); + } break; + default: break; + } + + uniform.count = size; + + return uniform; +} + bool ShaderBuilder::saveShaderFormat(const QString &path, const map &shaders, const VariantMap &user) { QDomDocument xml; QDomElement shader = xml.createElement("shader"); @@ -389,52 +547,12 @@ bool ShaderBuilder::saveShaderFormat(const QString &path, const mapsecond.toList()) { QDomElement property(xml.createElement("property")); - VariantList fields = p.toList(); - - auto field = fields.begin(); - Variant value = *field; - ++field; - uint32_t size = field->toInt(); - ++field; - - property.setAttribute("name", field->toString().c_str()); - - string type; - switch(value.userType()) { - case MetaType::BOOLEAN: { - type = "bool"; - size /= sizeof(bool); - } break; - case MetaType::INTEGER: { - type = "int"; - size /= sizeof(int); - } break; - case MetaType::FLOAT: { - type = "float"; - size /= sizeof(float); - } break; - case MetaType::VECTOR2: { - type = "vec2"; - size /= sizeof(Vector2); - } break; - case MetaType::VECTOR3: { - type = "vec3"; - size /= sizeof(Vector3); - } break; - case MetaType::VECTOR4: { - type = "vec4"; - size /= sizeof(Vector4); - } break; - case MetaType::MATRIX4: { - type = "mat4"; - size /= sizeof(Matrix4); - } break; - default: break; - } + Uniform uniform = uniformFromVariant(p); - property.setAttribute("type", type.c_str()); - if(size > 1) { - property.setAttribute("count", size); + property.setAttribute("name", uniform.name.c_str()); + property.setAttribute("type", uniform.typeName.c_str()); + if(uniform.count > 1) { + property.setAttribute("count", uniform.count); } properties.appendChild(property); @@ -691,7 +809,7 @@ bool ShaderBuilder::parseProperties(const QDomElement &element, VariantMap &user return true; } -VariantList ShaderBuilder::parsePassProperties(const QDomElement &element, int &materialType) { +VariantList ShaderBuilder::parsePassProperties(const QDomElement &element, int &materialType, int &lightingModel) { static const QMap materialTypes = { {"Surface", Material::Surface}, {"PostProcess", Material::PostProcess}, @@ -708,7 +826,8 @@ VariantList ShaderBuilder::parsePassProperties(const QDomElement &element, int & materialType = materialTypes.value(element.attribute("type"), Material::Surface); properties.push_back(materialType); properties.push_back(element.attribute(gTwoSided, "true") == "true"); - properties.push_back(lightingModels.value(element.attribute(gLightModel), Material::Unlit)); + lightingModel = lightingModels.value(element.attribute(gLightModel), Material::Unlit); + properties.push_back(lightingModel); properties.push_back(element.attribute(gWireFrame, "false") == "true"); return properties; diff --git a/modules/editor/shadertools/converter/shaderbuilder.h b/modules/editor/shadertools/converter/shaderbuilder.h index c8d34bcfa..ac25a3349 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.h +++ b/modules/editor/shadertools/converter/shaderbuilder.h @@ -13,7 +13,6 @@ #define STATIC "Static" #define SKINNED "Skinned" #define PARTICLE "Particle" -#define FULLSCREEN "Fullscreen" #define GEOMETRY "Geometry" @@ -58,6 +57,17 @@ class ShaderBuilderSettings : public AssetConverterSettings { }; +struct Uniform { + string name; + + string typeName; + + int count = 1; + + int type; + +}; + class ShaderBuilder : public AssetConverter { public: typedef map PragmaMap; @@ -73,6 +83,8 @@ class ShaderBuilder : public AssetConverter { static ShaderBuilderSettings::Rhi currentRhi(); + static void buildInstanceData(const VariantMap &user, PragmaMap &pragmas); + static VariantList toVariant(Material::BlendState blendState); static VariantList toVariant(Material::DepthState depthState); static VariantList toVariant(Material::StencilState stencilState); @@ -100,7 +112,11 @@ class ShaderBuilder : public AssetConverter { static Material::StencilState loadStencilState(const QDomElement &element); static void saveStencilState(const Material::StencilState &state, QDomDocument &document, QDomElement &parent); + static void compileData(VariantMap &data); + private: + static Uniform uniformFromVariant(const Variant &variant); + QString templatePath() const Q_DECL_OVERRIDE; QStringList suffixes() const Q_DECL_OVERRIDE; @@ -110,14 +126,14 @@ class ShaderBuilder : public AssetConverter { Actor *createActor(const AssetConverterSettings *settings, const QString &guid) const Q_DECL_OVERRIDE; - Variant compile(ShaderBuilderSettings::Rhi rhi, const string &buff, SpirVConverter::Inputs &inputs, int stage) const; + static Variant compile(ShaderBuilderSettings::Rhi rhi, const string &buff, SpirVConverter::Inputs &inputs, int stage); bool parseShaderFormat(const QString &path, VariantMap &data, bool compute = false); bool saveShaderFormat(const QString &path, const map &shaders, const VariantMap &user); bool parseProperties(const QDomElement &element, VariantMap &user); - VariantList parsePassProperties(const QDomElement &element, int &materialType); + VariantList parsePassProperties(const QDomElement &element, int &materialType, int &lightingModel); void parsePassV0(const QDomElement &element, VariantMap &user); void parsePassV11(const QDomElement &element, VariantMap &user); diff --git a/modules/editor/shadertools/converter/shadernodegraph.cpp b/modules/editor/shadertools/converter/shadernodegraph.cpp index ccd3e473d..e919f8770 100644 --- a/modules/editor/shadertools/converter/shadernodegraph.cpp +++ b/modules/editor/shadertools/converter/shadernodegraph.cpp @@ -562,7 +562,7 @@ bool ShaderNodeGraph::buildGraph(GraphNode *node) { return true; } -VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) const { +VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) { if(root == nullptr) { root = static_cast(m_rootNode); } @@ -612,70 +612,52 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) const { } user[UNIFORMS] = uniforms; + ShaderBuilder::buildInstanceData(user, m_pragmas); + Material::BlendState blend = root->blendState(); string define; - if(blend.sourceColorBlendMode == Material::BlendFactor::One && - blend.destinationColorBlendMode == Material::BlendFactor::One) { - define = "#define BLEND_ADDITIVE 1"; - } else if(blend.sourceColorBlendMode == Material::BlendFactor::SourceAlpha && - blend.destinationColorBlendMode == Material::BlendFactor::OneMinusSourceAlpha) { - define = "#define BLEND_TRANSLUCENT 1"; - } else if(!blend.enabled) { - define = "#define BLEND_OPAQUE 1"; - } - - switch(root->lightModel()) { - case ShaderRootNode::Lit: { - define += "\n#define MODEL_LIT 1"; - - VariantList data; - data.push_back(""); // path - data.push_back(LOCAL_BIND + 1); // binding - data.push_back("radianceMap"); // name - data.push_back(ShaderRootNode::Target); // flags - textures.push_back(data); - - } break; - case ShaderRootNode::Subsurface: { - define += "\n#define MODEL_SUBSURFACE 1"; - } break; - default: { - define += "\n#define MODEL_UNLIT 1"; - } break; + define += "\n#define USE_GBUFFER"; + + if(root->lightModel() == ShaderRootNode::Lit) { + define += "\n#define USE_TBN"; + + VariantList data; + data.push_back(""); // path + data.push_back(LOCAL_BIND + 1); // binding + data.push_back("radianceMap"); // name + data.push_back(ShaderRootNode::Target); // flags + textures.push_back(data); } // Pixel shader - string fragment = "Shader.frag"; + string file = "Shader.frag"; { - Variant data = ShaderBuilder::loadIncludes(fragment, define, m_pragmas); + Variant data = ShaderBuilder::loadIncludes(file, define, m_pragmas); if(data.isValid()) { user[FRAGMENT] = data; } } if(root->materialType() == ShaderRootNode::Surface && !editor) { define += "\n#define VISIBILITY_BUFFER 1"; - Variant data = ShaderBuilder::loadIncludes(fragment, define, m_pragmas); + Variant data = ShaderBuilder::loadIncludes(file, define, m_pragmas); if(data.isValid()) { user[VISIBILITY] = data; } } // Vertex shader - { - Variant data = ShaderBuilder::loadIncludes("Fullscreen.vert", define, m_pragmas); - if(data.isValid()) { - user[FULLSCREEN] = data; - } + file = "Static.vert"; + if(root->materialType() == ShaderRootNode::PostProcess) { + file = "Fullscreen.vert"; } - { - Variant data = ShaderBuilder::loadIncludes("Static.vert", define, m_pragmas); - if(data.isValid()) { - user[STATIC] = data; - } + Variant data = ShaderBuilder::loadIncludes(file, define, m_pragmas); + if(data.isValid()) { + user[STATIC] = data; } + if(root->materialType() == ShaderRootNode::Surface && !editor) { - { + if(root->useWithSkinned()) { Variant data = ShaderBuilder::loadIncludes("Skinned.vert", define, m_pragmas); if(data.isValid()) { user[SKINNED] = data; @@ -688,7 +670,7 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) const { textures.push_back(data); } } - { + if(root->useWithParticles()){ Variant data = ShaderBuilder::loadIncludes("Billboard.vert", define, m_pragmas); if(data.isValid()) { user[PARTICLE] = data; @@ -780,7 +762,6 @@ QString ShaderNodeGraph::buildFrom(GraphNode *node, Stage stage) { name.replace(" ", ""); QString value; - QString type = ShaderNode::typeToString(port.m_type); bool isDefault = true; const Link *link = findLink(node, &port); @@ -866,17 +847,20 @@ void ShaderNodeGraph::updatePreviews(CommandBuffer &buffer) { if(it.second.isVisible) { if(it.second.isDirty) { if(buildGraph(it.first)) { - it.second.material->loadUserData(data(true, &m_previewSettings)); + VariantMap data = ShaderNodeGraph::data(true, &m_previewSettings); + ShaderBuilder::compileData(data); + + it.second.material->loadUserData(data); if(it.second.instance) { delete it.second.instance; } - it.second.instance = it.second.material->createInstance(Material::Fullscreen); + it.second.instance = it.second.material->createInstance(Material::Static); it.second.isDirty = false; } } buffer.setRenderTarget(it.second.target); buffer.clearRenderTarget(true, Vector4(0, 0, 0, 1)); - buffer.drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::TRANSLUCENT, it.second.instance); + buffer.drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::TRANSLUCENT, *it.second.instance); } } } diff --git a/modules/editor/shadertools/converter/shadernodegraph.h b/modules/editor/shadertools/converter/shadernodegraph.h index 8fb41f49b..532c533fc 100644 --- a/modules/editor/shadertools/converter/shadernodegraph.h +++ b/modules/editor/shadertools/converter/shadernodegraph.h @@ -29,7 +29,7 @@ class ShaderNodeGraph : public AbstractNodeGraph { ShaderNodeGraph(); ~ShaderNodeGraph() Q_DECL_OVERRIDE; - VariantMap data(bool editor = false, ShaderRootNode *root = nullptr) const; + VariantMap data(bool editor = false, ShaderRootNode *root = nullptr); bool buildGraph(GraphNode *node = nullptr); diff --git a/modules/editor/shadertools/editor/materialedit.cpp b/modules/editor/shadertools/editor/materialedit.cpp index 668d03614..c72f45fbd 100644 --- a/modules/editor/shadertools/editor/materialedit.cpp +++ b/modules/editor/shadertools/editor/materialedit.cpp @@ -155,9 +155,10 @@ void MaterialEdit::saveAsset(const QString &path) { void MaterialEdit::onGraphUpdated() { if(m_builder && m_graph->buildGraph()) { VariantMap data = m_graph->data(true); - m_material->loadUserData(data); - m_codeDlg.setData(data); + + ShaderBuilder::compileData(data); + m_material->loadUserData(data); } } diff --git a/modules/editor/shadertools/shaders/Billboard.vert b/modules/editor/shadertools/shaders/Billboard.vert index 286578688..34620176f 100644 --- a/modules/editor/shadertools/shaders/Billboard.vert +++ b/modules/editor/shadertools/shaders/Billboard.vert @@ -3,12 +3,12 @@ #pragma flags #include "ShaderLayout.h" -#include "VertexFactory.h" layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; layout(location = 2) in vec4 color; -#ifdef MODEL_LIT + +#ifdef USE_TBN layout(location = 3) in vec3 normal; layout(location = 4) in vec3 tangent; #endif @@ -21,24 +21,25 @@ layout(location = 10) in vec4 particleRes2; layout(location = 0) out vec4 _vertex; layout(location = 1) out vec2 _uv0; layout(location = 2) out vec4 _color; -#ifdef MODEL_LIT + +#ifdef USE_TBN layout(location = 3) out vec3 _n; layout(location = 4) out vec3 _t; layout(location = 5) out vec3 _b; #endif -layout(location = 6) out vec3 _view; -layout(location = 7) out mat4 _modelView; -#pragma uniforms +layout(location = 6) out vec3 _view; +layout(location = 7) out int _instanceOffset; +layout(location = 8) out mat4 _modelView; #pragma functions void main(void) { -#pragma instance +#pragma offset - mat4 model = getModelMatrix(); +#pragma instance - _modelView = g.view * model; + _modelView = g.view * modelMatrix; vec3 camera = vec3(g.view[0].w, g.view[1].w, @@ -61,15 +62,17 @@ void main(void) { vec3 up = normalize(cross(normal, right)); vec4 v = vec4((up * x + right * y) * particleSizeDist.xyz + particlePosRot.xyz + PositionOffset, 1.0); - #ifdef MODEL_LIT + + #ifdef USE_TBN _t = tangent; _n = normal; _b = cross(_t, _n); #endif + _vertex = g.projection * (_modelView * v); - _view = normalize((model * v).xyz - camera); + _view = normalize((modelMatrix * v).xyz - camera); - _color = color * getLocalColor(); + _color = color; _uv0 = uv0; gl_Position = _vertex; } diff --git a/modules/editor/shadertools/shaders/Shader.frag b/modules/editor/shadertools/shaders/Shader.frag index 4c63bae7b..8969e7174 100644 --- a/modules/editor/shadertools/shaders/Shader.frag +++ b/modules/editor/shadertools/shaders/Shader.frag @@ -7,20 +7,24 @@ layout(location = 0) in vec4 _vertex; layout(location = 1) in vec2 _uv0; layout(location = 2) in vec4 _color; -#ifdef MODEL_LIT -layout(location = 3) in vec3 _n; -layout(location = 4) in vec3 _t; -layout(location = 5) in vec3 _b; + +#ifdef USE_TBN + layout(binding = LOCAL + 1) uniform sampler2D radianceMap; + + layout(location = 3) in vec3 _n; + layout(location = 4) in vec3 _t; + layout(location = 5) in vec3 _b; #endif layout(location = 6) in vec3 _view; -layout(location = 7) in mat4 _modelView; +layout(location = 7) flat in int _instanceOffset; +layout(location = 8) in mat4 _modelView; layout(location = 0) out vec4 gbuffer0; -#ifdef BLEND_OPAQUE -layout(location = 1) out vec4 gbuffer1; -layout(location = 2) out vec4 gbuffer2; -layout(location = 3) out vec4 gbuffer3; +#ifdef USE_GBUFFER + layout(location = 1) out vec4 gbuffer1; + layout(location = 2) out vec4 gbuffer2; + layout(location = 3) out vec4 gbuffer3; #endif #pragma uniforms @@ -30,6 +34,8 @@ layout(location = 3) out vec4 gbuffer3; #pragma functions void main(void) { +#pragma instance + vec3 Diffuse; vec3 Emissive; vec3 Normal; @@ -52,16 +58,12 @@ void main(void) { return; #endif -#ifndef BLEND_OPAQUE - gbuffer0 = vec4(emit, alpha); -#endif - -#ifdef BLEND_OPAQUE +#ifdef USE_GBUFFER float model = 0.0f; vec3 normal = vec3(1.0f); vec3 albedo = Diffuse * _color.xyz; - #ifdef MODEL_LIT + #ifdef USE_TBN normal = Normal * 2.0f - 1.0f; normal = normalize(normal.x * _t + normal.y * _b + normal.z * _n); @@ -76,6 +78,10 @@ void main(void) { gbuffer1 = vec4(normal, model); gbuffer2 = vec4(albedo, model); gbuffer3 = vec4(Roughness, 0.0f, Metallic, 1.0f); // Variables + +#else + gbuffer0 = vec4(emit, alpha); + #endif } diff --git a/modules/editor/shadertools/shaders/ShaderLayout.h b/modules/editor/shadertools/shaders/ShaderLayout.h index dce5a1879..4a332a085 100644 --- a/modules/editor/shadertools/shaders/ShaderLayout.h +++ b/modules/editor/shadertools/shaders/ShaderLayout.h @@ -22,8 +22,8 @@ layout(set = 1, binding = GLOBAL) uniform Global { float padding[13]; } g; +#ifndef NO_INSTANCE layout(std140, set = 1, binding = LOCAL) uniform InstanceData { vec4 data[4096]; } instance; - -layout(binding = LOCAL + 1) uniform sampler2D radianceMap; +#endif diff --git a/modules/editor/shadertools/shaders/Skinned.vert b/modules/editor/shadertools/shaders/Skinned.vert index 825c97d4b..8a34b4736 100644 --- a/modules/editor/shadertools/shaders/Skinned.vert +++ b/modules/editor/shadertools/shaders/Skinned.vert @@ -3,14 +3,14 @@ #pragma flags #include "ShaderLayout.h" -#include "VertexFactory.h" layout(binding = LOCAL + 2) uniform sampler2D skinMatrices; layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; layout(location = 2) in vec4 color; -#ifdef MODEL_LIT + +#ifdef USE_TBN layout(location = 3) in vec3 normal; layout(location = 4) in vec3 tangent; #endif @@ -21,25 +21,25 @@ layout(location = 6) in vec4 skinnedWeights; layout(location = 0) out vec4 _vertex; layout(location = 1) out vec2 _uv0; layout(location = 2) out vec4 _color; -#ifdef MODEL_LIT + +#ifdef USE_TBN layout(location = 3) out vec3 _n; layout(location = 4) out vec3 _t; layout(location = 5) out vec3 _b; #endif layout(location = 6) out vec3 _view; -layout(location = 7) out mat4 _modelView; - -#pragma uniforms +layout(location = 7) out int _instanceOffset; +layout(location = 8) out mat4 _modelView; #pragma functions void main(void) { -#pragma instance +#pragma offset - mat4 model = getModelMatrix(); +#pragma instance - _modelView = g.view * model; + _modelView = g.view * modelMatrix; vec3 camera = vec3(g.view[0].w, g.view[1].w, @@ -68,7 +68,8 @@ void main(void) { vec4(m1.w, m2.w, m3.w, 1.0)); finalVector += (m44 * vec4(vertex, 1.0)) * weights.x; - #ifdef MODEL_LIT + + #ifdef USE_TBN mat3 m33 = mat3(m44[0].xyz, m44[1].xyz, m44[2].xyz); @@ -76,11 +77,13 @@ void main(void) { _n += m33 * normal * weights.x; _t += m33 * tangent * weights.x; #endif + bones = bones.yzwx; weights = weights.yzwx; } } - #ifdef MODEL_LIT + + #ifdef USE_TBN _b = cross(_t, _n); #endif @@ -88,7 +91,7 @@ void main(void) { _vertex = g.projection * (g.view * vec4(v, 1.0)); _view = normalize(v - g.cameraPosition.xyz); - _color = color * getLocalColor(); + _color = color; _uv0 = uv0; gl_Position = _vertex; } diff --git a/modules/editor/shadertools/shaders/Static.vert b/modules/editor/shadertools/shaders/Static.vert index 2fb34b716..ef955056b 100644 --- a/modules/editor/shadertools/shaders/Static.vert +++ b/modules/editor/shadertools/shaders/Static.vert @@ -3,12 +3,12 @@ #pragma flags #include "ShaderLayout.h" -#include "VertexFactory.h" layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; layout(location = 2) in vec4 color; -#ifdef MODEL_LIT + +#ifdef USE_TBN layout(location = 3) in vec3 normal; layout(location = 4) in vec3 tangent; #endif @@ -16,23 +16,23 @@ layout(location = 2) in vec4 color; layout(location = 0) out vec4 _vertex; layout(location = 1) out vec2 _uv0; layout(location = 2) out vec4 _color; -#ifdef MODEL_LIT + +#ifdef USE_TBN layout(location = 3) out vec3 _n; layout(location = 4) out vec3 _t; layout(location = 5) out vec3 _b; #endif -layout(location = 6) out vec3 _view; -layout(location = 7) out mat4 _modelView; -#pragma uniforms +layout(location = 6) out vec3 _view; +layout(location = 7) out int _instanceOffset; +layout(location = 8) out mat4 _modelView; #pragma functions void main(void) { -#pragma instance +#pragma offset - mat4 modelMatrix = getModelMatrix(); - vec4 localColor = getLocalColor(); +#pragma instance _modelView = g.view * modelMatrix; @@ -44,8 +44,8 @@ void main(void) { #pragma vertex - #ifdef MODEL_LIT - mat3 rot = mat3(model); + #ifdef USE_TBN + mat3 rot = mat3(modelMatrix); _t = normalize(rot * tangent); _n = normalize(rot * normal); _b = cross(_t, _n); @@ -54,7 +54,7 @@ void main(void) { _vertex = g.projection * (_modelView * v); _view = normalize((modelMatrix * v).xyz - g.cameraPosition.xyz); - _color = color * localColor; + _color = color; _uv0 = uv0; gl_Position = _vertex; } diff --git a/modules/editor/shadertools/shaders/VertexFactory.h b/modules/editor/shadertools/shaders/VertexFactory.h deleted file mode 100644 index 25ce72f2a..000000000 --- a/modules/editor/shadertools/shaders/VertexFactory.h +++ /dev/null @@ -1,12 +0,0 @@ -const int structSize = 8; - -mat4 getModelMatrix() { - return mat4(instance.data[gl_InstanceIndex * structSize + 0], - instance.data[gl_InstanceIndex * structSize + 1], - instance.data[gl_InstanceIndex * structSize + 2], - instance.data[gl_InstanceIndex * structSize + 3]); -} - -vec4 getLocalColor() { - return vec4(instance.data[gl_InstanceIndex * structSize + 4]); -} diff --git a/modules/editor/shadertools/shadertools.qrc b/modules/editor/shadertools/shadertools.qrc index 437aee4a5..0aa741673 100644 --- a/modules/editor/shadertools/shadertools.qrc +++ b/modules/editor/shadertools/shadertools.qrc @@ -3,7 +3,6 @@ shaders/BRDF.h shaders/ShaderLayout.h shaders/Default.frag - shaders/VertexFactory.h templates/Material.mtl shaders/functions/hsvToRgb.mtlf shaders/functions/gammaToLinear.mtlf diff --git a/modules/renders/rendergl/includes/commandbuffergl.h b/modules/renders/rendergl/includes/commandbuffergl.h index d83524ce5..6296e1974 100644 --- a/modules/renders/rendergl/includes/commandbuffergl.h +++ b/modules/renders/rendergl/includes/commandbuffergl.h @@ -24,9 +24,9 @@ class CommandBufferGL : public CommandBuffer { void dispatchCompute(ComputeInstance *shader, int32_t groupsX, int32_t groupsY, int32_t groupsZ) override; - void drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) override; + void drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) override; - void drawMeshInstanced(const Matrix4 *models, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) override; + void drawMeshInstanced(const Matrix4 *models, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance, uint32_t count) override; void setRenderTarget(RenderTarget *target, uint32_t level = 0) override; @@ -47,7 +47,7 @@ class CommandBufferGL : public CommandBuffer { protected: uint32_t m_globalUbo; - uint32_t m_instanceUbo; + }; diff --git a/modules/renders/rendergl/includes/resources/materialgl.h b/modules/renders/rendergl/includes/resources/materialgl.h index 60d0ae1c9..d5ca6fc8b 100644 --- a/modules/renders/rendergl/includes/resources/materialgl.h +++ b/modules/renders/rendergl/includes/resources/materialgl.h @@ -28,14 +28,14 @@ class MaterialInstanceGL : public MaterialInstance { static void setStencilState(const Material::StencilState &state); private: - uint32_t m_instanceUbo; - Material::BlendState m_blendState; Material::DepthState m_depthState; Material::StencilState m_stencilState; + uint32_t m_instanceUbo; + }; class MaterialGL : public Material { @@ -47,11 +47,8 @@ class MaterialGL : public Material { enum ShaderType { VertexStatic = 1, - VertexStaticInst, VertexSkinned, - VertexSkinnedInst, VertexParticle, - VertexFullscreen, VertexLast, FragmentDefault, diff --git a/modules/renders/rendergl/src/commandbuffergl.cpp b/modules/renders/rendergl/src/commandbuffergl.cpp index de6db281b..bc8fbc8de 100644 --- a/modules/renders/rendergl/src/commandbuffergl.cpp +++ b/modules/renders/rendergl/src/commandbuffergl.cpp @@ -12,11 +12,8 @@ #include #include -#define INSTANCE_SIZE 4096 - CommandBufferGL::CommandBufferGL() : - m_globalUbo(0), - m_instanceUbo(0) { + m_globalUbo(0) { PROFILE_FUNCTION(); } @@ -40,15 +37,6 @@ void CommandBufferGL::begin() { glBindBuffer(GL_UNIFORM_BUFFER, m_globalUbo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Global), &m_globalUbo); glBindBuffer(GL_UNIFORM_BUFFER, 0); - - if(m_instanceUbo == 0) { - glGenBuffers(1, &m_instanceUbo); - glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(float) * INSTANCE_SIZE, nullptr, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - glBindBufferBase(GL_UNIFORM_BUFFER, LOCAL_BIND, m_instanceUbo); - } } void CommandBufferGL::clearRenderTarget(bool clearColor, const Vector4 &color, bool clearDepth, float depth) { @@ -82,36 +70,32 @@ void CommandBufferGL::dispatchCompute(ComputeInstance *shader, int32_t groupsX, #endif } -void CommandBufferGL::drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *instance) { +void CommandBufferGL::drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) { PROFILE_FUNCTION(); - drawMeshInstanced(&model, 1, mesh, sub, layer, instance); + drawMeshInstanced(&model, mesh, sub, layer, instance, 1); } -void CommandBufferGL::drawMeshInstanced(const Matrix4 *models, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *material) { +void CommandBufferGL::drawMeshInstanced(const Matrix4 *models, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &material, uint32_t count) { PROFILE_FUNCTION(); - if(mesh && material) { + if(mesh) { MeshGL *meshGL = static_cast(mesh); - m_local.model = *models; - - glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Local), &m_local); - glBindBuffer(GL_UNIFORM_BUFFER, 0); + material.setTransform(*models); - MaterialInstanceGL *instanceGL = static_cast(material); - if(instanceGL->bind(this, layer)) { + MaterialInstanceGL &instanceGL = static_cast(material); + if(instanceGL.bind(this, layer)) { meshGL->bindVao(this); if(meshGL->indices().empty()) { - int32_t glMode = (material->material()->wireframe()) ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; + int32_t glMode = (material.material()->wireframe()) ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; uint32_t vert = meshGL->vertices().size(); glDrawArraysInstanced(glMode, 0, vert, count); PROFILER_STAT(POLYGONS, index - 2 * count); } else { int32_t index = meshGL->indexCount(sub); - int32_t glMode = (material->material()->wireframe()) ? GL_LINES : GL_TRIANGLES; + int32_t glMode = (material.material()->wireframe()) ? GL_LINES : GL_TRIANGLES; glDrawElementsInstanced(glMode, index, GL_UNSIGNED_INT, reinterpret_cast(meshGL->indexStart(sub) * sizeof(int32_t)), count); PROFILER_STAT(POLYGONS, (index / 3) * count); } diff --git a/modules/renders/rendergl/src/resources/materialgl.cpp b/modules/renders/rendergl/src/resources/materialgl.cpp index 70ef03cfb..891ac92f3 100644 --- a/modules/renders/rendergl/src/resources/materialgl.cpp +++ b/modules/renders/rendergl/src/resources/materialgl.cpp @@ -9,15 +9,15 @@ #include +#define INSTANCE_SIZE 4096 + namespace { const char *gVisibility("Visibility"); const char *gDefault("Default"); const char *gStatic("Static"); - const char *gStaticInst("StaticInst"); const char *gSkinned("Skinned"); const char *gParticle("Particle"); - const char *gFullscreen("Fullscreen"); const char *gGeometry("Geometry"); }; @@ -30,10 +30,8 @@ void MaterialGL::loadUserData(const VariantMap &data) { {gDefault, FragmentDefault}, {gStatic, VertexStatic}, - {gStaticInst, VertexStaticInst}, {gSkinned, VertexSkinned}, {gParticle, VertexParticle}, - {gFullscreen, VertexFullscreen}, {gGeometry, GeometryDefault} }; @@ -231,12 +229,10 @@ MaterialInstance *MaterialGL::createInstance(SurfaceType type) { initInstance(result); if(result) { - uint16_t t = VertexStaticInst; + uint16_t t = VertexStatic; switch(type) { - case SurfaceType::Static: t = VertexStatic; break; case SurfaceType::Skinned: t = VertexSkinned; break; case SurfaceType::Billboard: t = VertexParticle; break; - case SurfaceType::Fullscreen: t = VertexFullscreen; break; default: break; } @@ -336,6 +332,7 @@ MaterialInstanceGL::MaterialInstanceGL(Material *material) : m_stencilState.passOperationBack = convertAction(m_stencilState.passOperationBack); m_stencilState.passOperationFront = convertAction(m_stencilState.passOperationFront); + } MaterialInstanceGL::~MaterialInstanceGL() { @@ -351,25 +348,22 @@ bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer) { if(program) { glUseProgram(program); - uint32_t size = material->uniformSize(); - if(size) { - if(m_instanceUbo == 0) { - glGenBuffers(1, &m_instanceUbo); - glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); - glBufferData(GL_UNIFORM_BUFFER, size, nullptr, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - } - - if(m_uniformDirty) { - glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, size, m_uniformBuffer); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - m_uniformDirty = false; - } + if(m_instanceUbo == 0) { + glGenBuffers(1, &m_instanceUbo); + glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); + glBufferData(GL_UNIFORM_BUFFER, sizeof(Vector4) * INSTANCE_SIZE, nullptr, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } - glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BIND, m_instanceUbo); + if(m_uniformDirty) { + glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, material->uniformSize(), m_uniformBuffer.data()); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + m_uniformDirty = false; } + glBindBufferBase(GL_UNIFORM_BUFFER, LOCAL_BIND, m_instanceUbo); + uint8_t i = 0; for(auto &it : material->textures()) { Texture *tex = it.texture; diff --git a/modules/uikit/src/components/frame.cpp b/modules/uikit/src/components/frame.cpp index caa31b37c..abc3165d7 100644 --- a/modules/uikit/src/components/frame.cpp +++ b/modules/uikit/src/components/frame.cpp @@ -69,10 +69,7 @@ void Frame::draw(CommandBuffer &buffer) { mat[12] -= verts[0].x; mat[13] -= verts[0].y; - buffer.setObjectId(actor()->uuid()); - buffer.setMaterialId(m_material->material()->uuid()); - - buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, m_material); + buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, *m_material); } } } diff --git a/modules/uikit/src/components/image.cpp b/modules/uikit/src/components/image.cpp index 37e38a9b0..da516e89f 100644 --- a/modules/uikit/src/components/image.cpp +++ b/modules/uikit/src/components/image.cpp @@ -15,7 +15,7 @@ namespace { const char *gBasemap = "BaseMap"; const char *gOverride = "mainTexture"; - const char *gColor = "color"; + const char *gColor = "mainColor"; const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; }; @@ -64,11 +64,7 @@ void Image::draw(CommandBuffer &buffer) { mat[12] -= verts[0].x; mat[13] -= verts[0].y; - buffer.setObjectId(actor()->uuid()); - buffer.setMaterialId((m_customMaterial) ? m_customMaterial->material()->uuid() : m_material->material()->uuid()); - buffer.setColor(m_color); - - buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, (m_customMaterial) ? m_customMaterial : m_material); + buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, (m_customMaterial) ? *m_customMaterial : *m_material); } } } diff --git a/modules/uikit/src/components/label.cpp b/modules/uikit/src/components/label.cpp index b3623ec6b..244b304b9 100644 --- a/modules/uikit/src/components/label.cpp +++ b/modules/uikit/src/components/label.cpp @@ -18,7 +18,9 @@ namespace { const char *gFont = "Font"; - const char *gOverride = "texture0"; + + const char *gColor = "mainColor"; + const char *gTexture = "mainTexture"; const char *gClipRect = "clipRect"; const char *gWeight = "weight"; }; @@ -63,11 +65,7 @@ void Label::draw(CommandBuffer &buffer) { if(m_mesh && !m_text.empty()) { Transform *t = actor()->transform(); if(t) { - buffer.setObjectId(actor()->uuid()); - buffer.setColor(m_color); - - buffer.setMaterialId(m_material->material()->uuid()); - buffer.drawMesh(t->worldTransform(), m_mesh, 0, CommandBuffer::UI, m_material); + buffer.drawMesh(t->worldTransform(), m_mesh, 0, CommandBuffer::UI, *m_material); } } } @@ -143,7 +141,7 @@ void Label::setFont(Font *font) { m_font->subscribe(&Label::fontUpdated, this); if(m_material) { - m_material->setTexture(gOverride, m_font->page()); + m_material->setTexture(gTexture, m_font->page()); } } @@ -174,6 +172,10 @@ Vector4 Label::color() const { */ void Label::setColor(const Vector4 color) { m_color = color; + + if(m_material) { + m_material->setVector4(gColor, &m_color); + } } /*! Returns true if word wrap enabled; otherwise returns false. diff --git a/worldeditor/bin/editor/materials/debug.shader b/worldeditor/bin/editor/materials/debug.shader index 076092e1c..bee430f87 100644 --- a/worldeditor/bin/editor/materials/debug.shader +++ b/worldeditor/bin/editor/materials/debug.shader @@ -1,6 +1,6 @@ - + diff --git a/worldeditor/bin/editor/materials/grid.shader b/worldeditor/bin/editor/materials/grid.shader index 2681231f9..eb1ad75ed 100644 --- a/worldeditor/bin/editor/materials/grid.shader +++ b/worldeditor/bin/editor/materials/grid.shader @@ -1,5 +1,6 @@ + @@ -15,35 +16,32 @@ layout(location = 2) in vec4 _color; layout(location = 3) in vec3 _n; layout(location = 4) in vec3 _t; layout(location = 5) in vec3 _b; +layout(location = 7) flat in int _instanceOffset; layout(location = 0) out vec4 rgb; const float subItems = 10.0; const float cellSize = 10.0; -layout(binding = UNIFORM) uniform Uniforms { - float scale; - float width; - bool ortho; -} uni; - void main() { +#pragma instance + vec3 pos = _vertex.xyz / _vertex.w; float fog = 1.0; - if(!uni.ortho) { - fog = clamp(_color.w * 100.0 * (1.0 - pos.z), 0.0, 1.0); + if(!ortho) { + fog = clamp(_color.w * mainColor.w * 100.0 * (1.0 - pos.z), 0.0, 1.0); } - float cell = uni.scale / subItems / cellSize; - float w = cell * 0.2 * uni.width; + float cell = scale / subItems / cellSize; + float w = cell * 0.2 * width; - vec2 offset = _uv0 * subItems * uni.scale; + vec2 offset = _uv0 * subItems * scale; if(mod(offset.x, cell) < w || mod(offset.y, cell) < w) { rgb = vec4(1.0, 0.0, 0.0, fog); if(mod(offset.x, cell * subItems) < w || mod(offset.y, cell * subItems) < w) { - rgb = vec4(_color.xyz, fog); + rgb = vec4(_color.xyz * mainColor.xyz, fog); } else { - rgb = vec4(_color.xyz, fog * 0.5 * (1.0 - uni.width)); + rgb = vec4(_color.xyz * mainColor.xyz, fog * 0.5 * (1.0 - width)); } } else { discard; diff --git a/worldeditor/bin/engine/materials/AreaLight.shader b/worldeditor/bin/engine/materials/AreaLight.shader index a53987cdf..c77c1f429 100644 --- a/worldeditor/bin/engine/materials/AreaLight.shader +++ b/worldeditor/bin/engine/materials/AreaLight.shader @@ -21,11 +21,14 @@ #pragma flags +#define NO_INSTANCE + #include "ShaderLayout.h" #include "Functions.h" #include "BRDF.h" -layout(binding = UNIFORM) uniform Uniforms { +layout(binding = LOCAL) uniform Uniforms { + mat4 model; mat4 matrix[6]; vec4 tiles[6]; vec4 color; diff --git a/worldeditor/bin/engine/materials/DefaultFont.shader b/worldeditor/bin/engine/materials/DefaultFont.shader index 7e11ff3e2..7b3d1a2b3 100644 --- a/worldeditor/bin/engine/materials/DefaultFont.shader +++ b/worldeditor/bin/engine/materials/DefaultFont.shader @@ -1,34 +1,33 @@ + - + - - - - 0.8999999761581421 - - - - - - - - - - - - - - - diff --git a/worldeditor/bin/engine/materials/DefaultMesh.shader b/worldeditor/bin/engine/materials/DefaultMesh.shader new file mode 100644 index 000000000..b032964f5 --- /dev/null +++ b/worldeditor/bin/engine/materials/DefaultMesh.shader @@ -0,0 +1,37 @@ + + + + + + + diff --git a/worldeditor/bin/engine/materials/DefaultMesh.mtl.set b/worldeditor/bin/engine/materials/DefaultMesh.shader.set similarity index 100% rename from worldeditor/bin/engine/materials/DefaultMesh.mtl.set rename to worldeditor/bin/engine/materials/DefaultMesh.shader.set diff --git a/worldeditor/bin/engine/materials/DefaultSprite.shader b/worldeditor/bin/engine/materials/DefaultSprite.shader index 07c8009e5..2d30b3c21 100644 --- a/worldeditor/bin/engine/materials/DefaultSprite.shader +++ b/worldeditor/bin/engine/materials/DefaultSprite.shader @@ -1,5 +1,6 @@ + diff --git a/worldeditor/bin/engine/materials/DirectLight.shader b/worldeditor/bin/engine/materials/DirectLight.shader index 17dd92174..f6b120f9c 100644 --- a/worldeditor/bin/engine/materials/DirectLight.shader +++ b/worldeditor/bin/engine/materials/DirectLight.shader @@ -17,6 +17,8 @@ - 0.5; bool rightHalf = _uv0.x > 0.5; @@ -41,16 +32,15 @@ void main(void) { uvSDF.x *= ratio; float borderRad; - float borderWidth = uni.borderWidth.x; if(rightHalf) { uvSDF.x = ratio - uvSDF.x; } if(upperHalf) { uvSDF.y = 1.0 - uvSDF.y; - borderRad = rightHalf ? uni.borderRadius.y : uni.borderRadius.x; + borderRad = rightHalf ? borderRadius.y : borderRadius.x; } else { - borderRad = rightHalf ? uni.borderRadius.z : uni.borderRadius.w; + borderRad = rightHalf ? borderRadius.z : borderRadius.w; } vec2 radSDF = uvSDF - borderRad; @@ -63,7 +53,7 @@ void main(void) { float surface = smoothstep(margin - softness, margin + softness, sdf); // Border - float width = (borderWidth > 0.0) ? max(fwidth(_uv0.y), borderWidth) : 0.0; + float width = (borderWidth.x > 0.0) ? max(fwidth(_uv0.y), borderWidth.x) : 0.0; float border = surface - smoothstep(margin, margin, sdf - width); float brd0 = step(1.0, ratio * _uv0.x + _uv0.y); @@ -75,9 +65,9 @@ void main(void) { float right = (1.0 - brd1) * (1.0 - brd2); float left = (1.0 - brd0) * (1.0 - brd3); - vec4 borderColor = mix(mix(mix(uni.bottomColor, uni.leftColor, left), uni.rightColor, right), uni.topColor, top); + vec4 borderColor = mix(mix(mix(bottomColor, leftColor, left), rightColor, right), topColor, top); - rgb = mix(vec4(uni.backgroundColor.xyz, uni.backgroundColor.w * surface), borderColor, border); + rgb = mix(vec4(backgroundColor.xyz, backgroundColor.w * surface), borderColor, border); } ]]> diff --git a/worldeditor/bin/engine/materials/Line.shader b/worldeditor/bin/engine/materials/Line.shader deleted file mode 100644 index 58a62d78f..000000000 --- a/worldeditor/bin/engine/materials/Line.shader +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - diff --git a/worldeditor/bin/engine/materials/Line.shader.set b/worldeditor/bin/engine/materials/Line.shader.set deleted file mode 100644 index b66fe9811..000000000 --- a/worldeditor/bin/engine/materials/Line.shader.set +++ /dev/null @@ -1,11 +0,0 @@ -{ - "guid": "{98a9448c-1698-4ffa-8729-0ebaa31ff833}", - "md5": "{0953c53a-7ae4-880d-74f9-b246a76a2063}", - "settings": { - "CurrentRHI": 1 - }, - "subitems": { - }, - "type": 48, - "version": 11 -} diff --git a/worldeditor/bin/engine/materials/Link.shader b/worldeditor/bin/engine/materials/Link.shader index 87fc24671..538826930 100644 --- a/worldeditor/bin/engine/materials/Link.shader +++ b/worldeditor/bin/engine/materials/Link.shader @@ -1,40 +1,16 @@ - - - - + From aa5ebc7c342049ce23a4a0772174c18e4098b762 Mon Sep 17 00:00:00 2001 From: Evgeny Prikazchikov Date: Mon, 29 Apr 2024 09:11:14 +0300 Subject: [PATCH 5/6] update --- engine/includes/commandbuffer.h | 4 +- engine/includes/components/particlerender.h | 16 +- engine/includes/components/textrender.h | 4 + engine/includes/components/tilemaprender.h | 2 + engine/includes/resources/material.h | 10 +- engine/includes/resources/particleeffect.h | 58 +--- engine/src/commandbuffer.cpp | 18 +- engine/src/components/meshrender.cpp | 4 +- engine/src/components/particlerender.cpp | 184 +++++----- engine/src/components/skinnedmeshrender.cpp | 4 +- engine/src/components/spriterender.cpp | 5 +- engine/src/components/textrender.cpp | 42 ++- engine/src/components/tilemaprender.cpp | 31 +- engine/src/editor/viewport/viewport.cpp | 11 +- engine/src/engine.cpp | 2 +- engine/src/gizmos.cpp | 12 +- engine/src/pipelinecontext.cpp | 2 +- engine/src/pipelinetasks/ambientocclusion.cpp | 6 +- engine/src/pipelinetasks/antialiasing.cpp | 2 +- engine/src/pipelinetasks/bloom.cpp | 6 +- engine/src/pipelinetasks/deferredlighting.cpp | 52 +-- engine/src/pipelinetasks/reflections.cpp | 4 +- engine/src/resources/material.cpp | 65 +++- engine/src/resources/particleeffect.cpp | 318 +++++++----------- engine/src/resources/tilemap.cpp | 12 +- .../editor/graph/graphwidgets/linksrender.cpp | 8 +- .../converter/functions/customfunction.h | 2 +- .../converter/functions/function.h | 4 +- .../converter/functions/materialparam.h | 4 +- .../converter/functions/matrixoperations.h | 2 +- .../converter/functions/texturesample.h | 8 +- .../shadertools/converter/shaderbuilder.cpp | 46 ++- .../shadertools/converter/shaderbuilder.h | 4 +- .../{shadernodegraph.cpp => shadergraph.cpp} | 88 ++--- .../{shadernodegraph.h => shadergraph.h} | 12 +- .../shadertools/editor/materialedit.cpp | 8 +- .../editor/shadertools/editor/materialedit.h | 4 +- .../editor/shadertools/shaders/Billboard.vert | 42 +-- .../editor/shadertools/shaders/Shader.frag | 2 +- .../shadertools/shaders/Visibility.frag | 15 + modules/editor/shadertools/shadertools.qrc | 1 + .../rendergl/includes/commandbuffergl.h | 4 +- .../rendergl/includes/resources/materialgl.h | 6 +- .../renders/rendergl/src/commandbuffergl.cpp | 46 ++- .../rendergl/src/resources/materialgl.cpp | 24 +- modules/uikit/src/components/frame.cpp | 4 +- modules/uikit/src/components/image.cpp | 5 +- modules/uikit/src/components/label.cpp | 4 +- .../bin/editor/materials/checkerboard.shader | 2 + worldeditor/bin/editor/materials/debug.shader | 2 + worldeditor/bin/editor/materials/gizmo.shader | 2 + .../bin/editor/materials/outline.shader | 9 +- worldeditor/bin/editor/materials/solid.shader | 2 + .../engine/materials/AmbientOcclusion.shader | 17 +- .../bin/engine/materials/AreaLight.shader | 12 +- worldeditor/bin/engine/materials/Blur.shader | 9 +- .../bin/engine/materials/BlurOcclusion.shader | 6 +- .../engine/materials/CombineOcclusion.shader | 10 +- .../bin/engine/materials/DefaultMesh.shader | 11 +- .../bin/engine/materials/DefaultSprite.shader | 9 +- .../bin/engine/materials/Downsample.shader | 9 +- worldeditor/bin/engine/materials/FXAA.shader | 6 +- .../engine/materials/IblReflections.shader | 18 +- worldeditor/bin/engine/materials/Link.shader | 2 + .../bin/engine/materials/PointLight.shader | 25 +- worldeditor/bin/engine/materials/SSLR.shader | 18 +- .../bin/engine/materials/SpotLight.shader | 25 +- 67 files changed, 742 insertions(+), 669 deletions(-) rename modules/editor/shadertools/converter/{shadernodegraph.cpp => shadergraph.cpp} (91%) rename modules/editor/shadertools/converter/{shadernodegraph.h => shadergraph.h} (93%) create mode 100644 modules/editor/shadertools/shaders/Visibility.frag diff --git a/engine/includes/commandbuffer.h b/engine/includes/commandbuffer.h index a2c40117b..c1a827dcc 100644 --- a/engine/includes/commandbuffer.h +++ b/engine/includes/commandbuffer.h @@ -54,9 +54,7 @@ class ENGINE_EXPORT CommandBuffer: public Object { virtual void dispatchCompute(ComputeInstance *shader, int32_t groupsX, int32_t groupsY, int32_t groupsZ); - virtual void drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance); - - virtual void drawMeshInstanced(const Matrix4 *transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance, uint32_t count); + virtual void drawMesh(Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance); virtual void setRenderTarget(RenderTarget *target, uint32_t level = 0); diff --git a/engine/includes/components/particlerender.h b/engine/includes/components/particlerender.h index 10c73320e..947265450 100644 --- a/engine/includes/components/particlerender.h +++ b/engine/includes/components/particlerender.h @@ -25,8 +25,8 @@ class ENGINE_EXPORT ParticleRender : public Renderable { void deltaUpdate(float dt); private: - inline void spawnParticle(ParticleEmitter &emitter, ParticleData &data); - void updateParticle(ParticleEmitter &emitter, ParticleData &data, float dt); + inline void spawnParticle(Matrix4 &matrix); + void updateParticle(ParticleData &data, float dt); AABBox bound() const override; @@ -40,16 +40,10 @@ class ENGINE_EXPORT ParticleRender : public Renderable { static void effectUpdated(int state, void *ptr); private: - typedef vector BufferArray; - typedef list ParticleList; + vector m_particles; - vector m_buffers; - vector m_particles; - - vector m_ejectionTime; - vector m_count; - - vector m_visibleCount; + float m_ejectionTime; + float m_count; AABBox m_aabb; diff --git a/engine/includes/components/textrender.h b/engine/includes/components/textrender.h index b7a3b08ae..98520019b 100644 --- a/engine/includes/components/textrender.h +++ b/engine/includes/components/textrender.h @@ -74,6 +74,8 @@ class ENGINE_EXPORT TextRender : public Renderable { AABBox localBound() const override; + void setMaterialsList(const list &materials) override; + void drawGizmosSelected() override; void loadData(const VariantList &data) override; @@ -101,6 +103,8 @@ class ENGINE_EXPORT TextRender : public Renderable { int m_alignment; + float m_fontWeight; + bool m_kerning; bool m_wrap; diff --git a/engine/includes/components/tilemaprender.h b/engine/includes/components/tilemaprender.h index 5c84072c3..2919dabb1 100644 --- a/engine/includes/components/tilemaprender.h +++ b/engine/includes/components/tilemaprender.h @@ -36,6 +36,8 @@ class ENGINE_EXPORT TileMapRender : public Renderable { void draw(CommandBuffer &buffer, uint32_t layer) override; + void setMaterialsList(const list &materials) override; + void loadUserData(const VariantMap &data) override; VariantMap saveUserData() const override; diff --git a/engine/includes/resources/material.h b/engine/includes/resources/material.h index 51b0980ab..82043ca31 100644 --- a/engine/includes/resources/material.h +++ b/engine/includes/resources/material.h @@ -270,6 +270,9 @@ class ENGINE_EXPORT MaterialInstance { Texture *texture(const char *name); + uint32_t instanceCount() const; + void setInstanceCount(uint32_t number); + void setBool(const char *name, const bool *value, int32_t count = 1); void setInteger(const char *name, const int32_t *value, int32_t count = 1); @@ -279,11 +282,14 @@ class ENGINE_EXPORT MaterialInstance { void setVector3(const char *name, const Vector3 *value, int32_t count = 1); void setVector4(const char *name, const Vector4 *value, int32_t count = 1); - void setTransform(const Matrix4 &tranform); void setMatrix4(const char *name, const Matrix4 *value, int32_t count = 1); + void setTransform(const Matrix4 &transform, uint32_t id); + virtual void setTexture(const char *name, Texture *texture); + vector &rawUniformBuffer(); + uint32_t paramCount() const; string paramName(uint32_t index) const; Variant paramValue(uint32_t index) const; @@ -304,6 +310,8 @@ class ENGINE_EXPORT MaterialInstance { Material *m_material; + uint32_t m_instanceCount; + uint16_t m_surfaceType; bool m_uniformDirty; diff --git a/engine/includes/resources/particleeffect.h b/engine/includes/resources/particleeffect.h index 9a9bb5311..17f2ab27a 100644 --- a/engine/includes/resources/particleeffect.h +++ b/engine/includes/resources/particleeffect.h @@ -74,25 +74,25 @@ class ENGINE_EXPORT ParticleModificator { Vector4 m_min; Vector4 m_max; - VariantAnimation m_Curve; + VariantAnimation m_curve; }; typedef std::deque ModifiersDeque; -class ENGINE_EXPORT ParticleEmitter { +class ENGINE_EXPORT ParticleEffect : public Resource { + A_REGISTER(ParticleEffect, Resource, Resources) + A_PROPERTIES( - A_PROPERTY(Mesh *, mesh, ParticleEmitter::mesh, ParticleEmitter::setMesh), - A_PROPERTY(Material *, material, ParticleEmitter::material, ParticleEmitter::setMaterial), - A_PROPERTY(float, distibution, ParticleEmitter::distribution, ParticleEmitter::setDistribution), - A_PROPERTY(bool, local, ParticleEmitter::local, ParticleEmitter::setLocal), - A_PROPERTY(bool, continous, ParticleEmitter::continous, ParticleEmitter::setContinous) + A_PROPERTY(Mesh *, mesh, ParticleEffect::mesh, ParticleEffect::setMesh), + A_PROPERTY(Material *, material, ParticleEffect::material, ParticleEffect::setMaterial), + A_PROPERTY(float, distibution, ParticleEffect::distribution, ParticleEffect::setDistribution), + A_PROPERTY(bool, local, ParticleEffect::local, ParticleEffect::setLocal), + A_PROPERTY(bool, continous, ParticleEffect::continous, ParticleEffect::setContinous) ) - A_NOMETHODS() public: - ParticleEmitter(); - - bool operator== (const ParticleEmitter &emitter) const; + ParticleEffect(); + ~ParticleEffect(); Mesh *mesh() const; void setMesh(Mesh *mesh); @@ -115,7 +115,9 @@ class ENGINE_EXPORT ParticleEmitter { ModifiersDeque &modifiers(); void setModifiers(const ModifiersDeque &modifiers); -private: + void loadUserData(const VariantMap &data) override; + +protected: ModifiersDeque m_modifiers; Mesh *m_mesh; @@ -130,38 +132,6 @@ class ENGINE_EXPORT ParticleEmitter { bool m_continous; -}; -typedef deque EmitterDeque; - -class ENGINE_EXPORT ParticleEffect : public Resource { - A_REGISTER(ParticleEffect, Resource, Resources) - - A_NOPROPERTIES() - A_METHODS( - A_METHOD(void, ParticleEffect::clear), - A_METHOD(int, ParticleEffect::emittersCount), - A_METHOD(ParticleEmitter *, ParticleEffect::emitter), - A_METHOD(void, ParticleEffect::addEmitter) - ) - -public: - ParticleEffect(); - ~ParticleEffect(); - - void clear(); - - int emittersCount() const; - - ParticleEmitter *emitter(int index); - void addEmitter(ParticleEmitter *emitter); - - void loadUserData(const VariantMap &data) override; - - static void registerSuper(ObjectSystem *system); - -protected: - EmitterDeque m_Emitters; - }; #endif // PARTICLEEFFECT_H diff --git a/engine/src/commandbuffer.cpp b/engine/src/commandbuffer.cpp index f183dea3d..9f99a9f27 100644 --- a/engine/src/commandbuffer.cpp +++ b/engine/src/commandbuffer.cpp @@ -43,28 +43,14 @@ void CommandBuffer::dispatchCompute(ComputeInstance *shader, int32_t groupsX, in A_UNUSED(groupsZ); } /*! - Draws a \a mesh with the specified \a sub mesh index in the \a transform location with assigned material \a instance, and rendering \a layer. + Draws a \a mesh with the specified \a sub mesh index with assigned material \a instance, and rendering \a layer. */ -void CommandBuffer::drawMesh(const Matrix4 &transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) { - A_UNUSED(transform); +void CommandBuffer::drawMesh(Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) { A_UNUSED(mesh); A_UNUSED(sub); A_UNUSED(layer); A_UNUSED(instance); } -/*! - Draws the same \a mesh multiple times using GPU instancing. - GPU will draw this mesh with the specified \a sub mesh index in different \a transform locations with assigned material \a instance, and rendering \a layer. - Parameter \a count specifies the number of instances to draw. -*/ -void CommandBuffer::drawMeshInstanced(const Matrix4 *transform, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance, uint32_t count) { - A_UNUSED(transform); - A_UNUSED(mesh); - A_UNUSED(sub); - A_UNUSED(layer); - A_UNUSED(instance); - A_UNUSED(count); -} /*! Sets the render \a target for subsequent rendering commands. Parameter \a level specifies the Mipmap level. diff --git a/engine/src/components/meshrender.cpp b/engine/src/components/meshrender.cpp index 3b5e64b94..a474d41c3 100644 --- a/engine/src/components/meshrender.cpp +++ b/engine/src/components/meshrender.cpp @@ -39,7 +39,9 @@ void MeshRender::draw(CommandBuffer &buffer, uint32_t layer) { for(int i = 0; i < m_mesh->subMeshCount(); i++) { MaterialInstance *instance = (i < m_materials.size()) ? m_materials[i] : nullptr; if(instance) { - buffer.drawMesh(transform, m_mesh, i, layer, *instance); + instance->setTransform(transform, a->uuid()); + + buffer.drawMesh(m_mesh, i, layer, *instance); } } } diff --git a/engine/src/components/particlerender.cpp b/engine/src/components/particlerender.cpp index 989fd0bda..65807de03 100644 --- a/engine/src/components/particlerender.cpp +++ b/engine/src/components/particlerender.cpp @@ -26,6 +26,8 @@ namespace { */ ParticleRender::ParticleRender() : + m_ejectionTime(0.0f), + m_count(0.0f), m_effect(nullptr) { } @@ -56,77 +58,66 @@ void ParticleRender::deltaUpdate(float dt) { if(m_effect) { m_aabb.setBox(Vector3(FLT_MAX), Vector3(-FLT_MAX)); - for(uint32_t index = 0; index < m_buffers.size(); index++) { - ParticleEmitter *emitter = m_effect->emitter(index); - - m_visibleCount[index] = 0; - uint32_t i = 0; - bool local = emitter->local(); - bool continous = emitter->continous(); - - // Spawn particles - m_count[index] += emitter->distribution() * dt; - while(isEnabled() && (continous || m_ejectionTime[index] > 0.0f) && m_count[index] >= 1.0f) { - ParticleData particle; - spawnParticle(*emitter, particle); - particle.transform = m * particle.position; - m_particles[index].push_back(particle); - m_count[index] -= 1.0f; - } + bool continous = m_effect->continous(); - if(m_buffers[index].size() < m_particles[index].size()) { - m_buffers[index].resize(m_particles[index].size()); - } + // Spawn particles + m_count += m_effect->distribution() * dt; + while(isEnabled() && (continous || m_ejectionTime > 0.0f) && m_count >= 1.0f) { + spawnParticle(m); + + m_count -= 1.0f; + } + + if(!continous) { + m_ejectionTime -= dt; + } + + // Update particles + bool local = m_effect->local(); + + uint32_t visibleCount = 0; + for(auto &particle : m_particles) { + particle.life -= dt; + if(particle.life >= 0.0f) { + updateParticle(particle, dt); - if(!continous) { - m_ejectionTime[index] -= dt; + particle.transform = (local) ? m * particle.position : particle.position; + particle.distance = (pos - particle.transform).sqrLength(); + + visibleCount++; } - // Update particles - for(auto &particle : m_particles[index]) { - particle.life -= dt; - if(particle.life >= 0.0f) { - updateParticle(*emitter, particle, dt); - - particle.transform = (local) ? m * particle.position : particle.position; - particle.distance = (pos - particle.transform).sqrLength(); - - m_visibleCount[index]++; - } else { - particle.distance = -1.0f; - if(isEnabled() && (continous || m_ejectionTime[index] > 0.0f) && m_count[index] >= 1.0f) { - spawnParticle(*emitter, particle); - particle.transform = m * particle.position; - m_count[index] -= 1.0f; - } - } - m_buffers[index][i].mat[0] = particle.transform.x; - m_buffers[index][i].mat[1] = particle.transform.y; - m_buffers[index][i].mat[2] = particle.transform.z; - - m_buffers[index][i].mat[3] = particle.angle.z; - - m_buffers[index][i].mat[4] = particle.size.x; - m_buffers[index][i].mat[5] = particle.size.y; - m_buffers[index][i].mat[6] = particle.size.z; - - m_buffers[index][i].mat[7] = particle.distance; - - m_buffers[index][i].mat[10] = particle.frame; - m_buffers[index][i].mat[11] = particle.life; - - m_buffers[index][i].mat[12] = particle.color.x; - m_buffers[index][i].mat[13] = particle.color.y; - m_buffers[index][i].mat[14] = particle.color.z; - m_buffers[index][i].mat[15] = particle.color.w; - - if(particle.life > 0.0f) { - m_aabb.encapsulate(particle.transform, particle.size.sqrLength()); - } - - i++; + + if(particle.life > 0.0f) { + m_aabb.encapsulate(particle.transform, particle.size.sqrLength()); } + } + + std::sort(m_particles.begin(), m_particles.end(), [](const ParticleData &left, const ParticleData &right) { return left.distance > right.distance; }); + + MaterialInstance &instance = *m_materials.front(); + + instance.setInstanceCount(visibleCount); + vector &uniformBuffer = instance.rawUniformBuffer(); + + Vector4 colorID(CommandBuffer::idToColor(actor()->uuid())); - std::sort(m_buffers[index].begin(), m_buffers[index].end(), [](const Matrix4 &left, const Matrix4 &right) { return left[7] > right[7]; }); + uint32_t offset = 0; + for(auto &particle : m_particles) { + if(particle.life > 0.0f) { + Vector4 v0(particle.transform, particle.angle.z); + memcpy(&uniformBuffer[offset], &v0, sizeof(Vector4)); + offset += sizeof(Vector4); + + Vector4 v1(particle.size, particle.distance); + memcpy(&uniformBuffer[offset], &v1, sizeof(Vector4)); + offset += sizeof(Vector4) * 2; + + memcpy(&uniformBuffer[offset], &colorID, sizeof(Vector4)); + offset += sizeof(Vector4); + + memcpy(&uniformBuffer[offset], &particle.color, sizeof(Vector4)); + offset += sizeof(Vector4); + } } } } @@ -136,13 +127,9 @@ void ParticleRender::deltaUpdate(float dt) { void ParticleRender::draw(CommandBuffer &buffer, uint32_t layer) { Actor *a = actor(); if(layer & a->layers()) { - for(uint32_t index = 0; index < m_buffers.size(); index++) { - MaterialInstance *instance = m_materials[index]; - if(m_visibleCount[index] > 0 && instance) { - ParticleEmitter *emitter = m_effect->emitter(index); - Matrix4 *transforms = m_buffers[index].data(); - buffer.drawMeshInstanced(transforms, emitter->mesh(), 0, layer, *instance, m_visibleCount[index]); - } + MaterialInstance *instance = m_materials.front(); + if(instance && instance->instanceCount() > 0) { + buffer.drawMesh(m_effect->mesh(), 0, layer, *instance); } } } @@ -173,23 +160,37 @@ void ParticleRender::setEffect(ParticleEffect *effect) { /*! \internal */ -void ParticleRender::spawnParticle(ParticleEmitter &emitter, ParticleData &data) { +void ParticleRender::spawnParticle(Matrix4 &matrix) { PROFILE_FUNCTION(); - data.position.x = 0.0f; - data.position.y = 0.0f; - data.position.z = 0.0f; - for(auto &it : emitter.modifiers()) { - it->spawnParticle(data); + ParticleData *particle = nullptr; + for(auto &it : m_particles) { + if(it.life <= 0.0f) { + particle = ⁢ + break; + } + } + + if(particle == nullptr) { + m_particles.push_back(ParticleData()); + particle = &m_particles.back(); + } + + if(particle) { + for(auto &it : m_effect->modifiers()) { + it->spawnParticle(*particle); + } + + particle->transform = matrix * particle->position; } } /*! \internal */ -void ParticleRender::updateParticle(ParticleEmitter &emitter, ParticleData &data, float dt) { +void ParticleRender::updateParticle(ParticleData &data, float dt) { PROFILE_FUNCTION(); - for(auto &it : emitter.modifiers()) { + for(auto &it : m_effect->modifiers()) { it->updateParticle(data, dt); } } @@ -234,30 +235,15 @@ void ParticleRender::effectUpdated(int state, void *ptr) { if(state == Resource::Ready) { ParticleRender *p = static_cast(ptr); - p->m_buffers.clear(); p->m_particles.clear(); - p->m_ejectionTime.clear(); - p->m_count.clear(); - p->m_visibleCount.clear(); for(auto it : p->m_materials) { delete it; } - int count = p->m_effect->emittersCount(); - - p->m_buffers.resize(count); - p->m_particles.resize(count); - p->m_ejectionTime.resize(count); - p->m_count.resize(count); - p->m_visibleCount.resize(count); - p->m_materials.resize(count); - - for(int32_t i = 0; i < p->m_effect->emittersCount(); i++) { - ParticleEmitter *emitter = p->m_effect->emitter(i); - if(emitter->material()) { - p->m_materials[i] = emitter->material()->createInstance(Material::Billboard); - } + if(p->m_effect->material()) { + p->m_materials.push_back(p->m_effect->material()->createInstance(Material::Billboard)); + // Need to map memory here } } } diff --git a/engine/src/components/skinnedmeshrender.cpp b/engine/src/components/skinnedmeshrender.cpp index 2c893ac50..cd71ea3df 100644 --- a/engine/src/components/skinnedmeshrender.cpp +++ b/engine/src/components/skinnedmeshrender.cpp @@ -44,7 +44,9 @@ void SkinnedMeshRender::draw(CommandBuffer &buffer, uint32_t layer) { for(int i = 0; i < m_mesh->subMeshCount(); i++) { MaterialInstance *instance = (i < m_materials.size()) ? m_materials[i] : nullptr; if(instance) { - buffer.drawMesh(transform, m_mesh, i, layer, *instance); + instance->setTransform(transform, a->uuid()); + + buffer.drawMesh(m_mesh, i, layer, *instance); } } } diff --git a/engine/src/components/spriterender.cpp b/engine/src/components/spriterender.cpp index 187f82637..024f512b8 100644 --- a/engine/src/components/spriterender.cpp +++ b/engine/src/components/spriterender.cpp @@ -68,7 +68,10 @@ void SpriteRender::draw(CommandBuffer &buffer, uint32_t layer) { Transform *t = a->transform(); if(t) { - buffer.drawMesh(t->worldTransform(), (m_customMesh) ? m_customMesh : m_mesh, 0, layer, *m_materials.front()); + MaterialInstance &instance = *m_materials.front(); + instance.setTransform(t->worldTransform(), a->uuid()); + + buffer.drawMesh((m_customMesh) ? m_customMesh : m_mesh, 0, layer, instance); } } } diff --git a/engine/src/components/textrender.cpp b/engine/src/components/textrender.cpp index 944d5294e..908317951 100644 --- a/engine/src/components/textrender.cpp +++ b/engine/src/components/textrender.cpp @@ -14,7 +14,9 @@ namespace { const char *gFont = "Font"; - const char *gOverride = "mainTexture"; + const char *gColor = "mainColor"; + const char *gTexture = "mainTexture"; + const char *gWeight = "weight"; }; /*! @@ -31,6 +33,7 @@ TextRender::TextRender() : m_mesh(Engine::objectCreate()), m_size(16), m_alignment(Left), + m_fontWeight(0.5f), m_kerning(true), m_wrap(false) { @@ -39,8 +42,7 @@ TextRender::TextRender() : Material *material = Engine::loadResource(".embedded/DefaultFont.shader"); if(material) { MaterialInstance *instance = material->createInstance(); - float fontWeight = 0.5f; - instance->setFloat("weight", &fontWeight); + instance->setFloat(gWeight, &m_fontWeight); m_materials.push_back(instance); } @@ -59,7 +61,10 @@ void TextRender::draw(CommandBuffer &buffer, uint32_t layer) { if(m_mesh && !m_materials.empty() && layer & a->layers() && !m_text.empty()) { Transform *t = a->transform(); if(t) { - buffer.drawMesh(t->worldTransform(), m_mesh, 0, layer, *m_materials.front()); + MaterialInstance &instance = *m_materials.front(); + instance.setTransform(t->worldTransform(), a->uuid()); + + buffer.drawMesh(m_mesh, 0, layer, instance); } } } @@ -95,8 +100,8 @@ void TextRender::setFont(Font *font) { if(m_font) { m_font->subscribe(&TextRender::fontUpdated, this); - if(!m_materials.empty()) { - m_materials.front()->setTexture(gOverride, m_font->page()); + for(auto it : m_materials) { + it->setTexture(gTexture, m_font->page()); } } composeMesh(m_font, m_mesh, m_size, m_text, m_alignment, m_kerning, m_wrap, m_boundaries); @@ -108,8 +113,11 @@ void TextRender::setFont(Font *font) { void TextRender::setMaterial(Material *material) { Renderable::setMaterial(material); - if(m_font && !m_materials.empty()) { - m_materials.front()->setTexture(gOverride, m_font->page()); + if(m_font) { + for(auto it : m_materials) { + it->setTexture(gTexture, m_font->page()); + it->setFloat(gWeight, &m_fontWeight); + } } } /*! @@ -137,7 +145,7 @@ Vector4 TextRender::color() const { void TextRender::setColor(const Vector4 color) { m_color = color; for(auto it : m_materials) { - it->setVector4("mainColor", &m_color); + it->setVector4(gColor, &m_color); } } /*! @@ -249,6 +257,7 @@ AABBox TextRender::localBound() const { if(m_mesh) { return m_mesh->bound(); } + return Renderable::localBound(); } /*! @@ -445,11 +454,26 @@ Vector2 TextRender::cursorPosition(Font *font, int size, const string &text, boo return pos; } + return Vector2(); } /*! \internal */ +void TextRender::setMaterialsList(const list &materials) { + Renderable::setMaterialsList(materials); + + for(auto it : m_materials) { + if(m_font) { + it->setTexture(gTexture, m_font->page()); + } + it->setVector4(gColor, &m_color); + it->setFloat(gWeight, &m_fontWeight); + } +} +/*! + \internal +*/ void TextRender::drawGizmosSelected() { AABBox box = bound(); Gizmos::drawWireBox(box.center, box.extent * 2.0f, Vector4(1.0f)); diff --git a/engine/src/components/tilemaprender.cpp b/engine/src/components/tilemaprender.cpp index 0d041af4e..a15102639 100644 --- a/engine/src/components/tilemaprender.cpp +++ b/engine/src/components/tilemaprender.cpp @@ -15,7 +15,8 @@ namespace { const char *gTileMap = "TileMap"; const char *gMaterial = "Material"; - const char *gOverride = "mainTexture"; + const char *gColor = "mainColor"; + const char *gTexture = "mainTexture"; const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; } @@ -47,7 +48,10 @@ void TileMapRender::draw(CommandBuffer &buffer, uint32_t layer) { if(m_tileMap && !m_materials.empty() && layer & a->layers()) { Transform *t = a->transform(); if(t) { - buffer.drawMesh(t->worldTransform(), m_tileMap->tileMesh(), 0, layer, *m_materials.front()); + MaterialInstance &instance = *m_materials.front(); + instance.setTransform(t->worldTransform(), a->uuid()); + + buffer.drawMesh(m_tileMap->tileMesh(), 0, layer, instance); } } } @@ -82,8 +86,10 @@ void TileMapRender::setTileMap(TileMap *map) { TileSet *tileSet = m_tileMap->tileSet(); if(tileSet) { Texture *texture = tileSet->spriteSheet() ? tileSet->spriteSheet()->page() : nullptr; - if(texture && !m_materials.empty()) { - m_materials.front()->setTexture(gOverride, texture); + Vector4 color(1.0f); + for(auto it : m_materials) { + it->setTexture(gTexture, texture); + it->setVector4(gColor, &color); } } } @@ -103,8 +109,10 @@ void TileMapRender::setMaterial(Material *material) { if(sheet) { texture = sheet->page(); } - if(texture && !m_materials.empty()) { - m_materials.front()->setTexture(gOverride, texture); + Vector4 color(1.0f); + for(auto it : m_materials) { + it->setTexture(gTexture, texture); + it->setVector4(gColor, &color); } } } @@ -125,6 +133,17 @@ void TileMapRender::setLayer(int layer) { /*! \internal */ +void TileMapRender::setMaterialsList(const list &materials) { + Renderable::setMaterialsList(materials); + + Vector4 color(1.0f); + for(auto it : m_materials) { + it->setVector4(gColor, &color); + } +} +/*! + \internal +*/ void TileMapRender::loadUserData(const VariantMap &data) { Component::loadUserData(data); { diff --git a/engine/src/editor/viewport/viewport.cpp b/engine/src/editor/viewport/viewport.cpp index 4aae5bdff..84911eb6e 100644 --- a/engine/src/editor/viewport/viewport.cpp +++ b/engine/src/editor/viewport/viewport.cpp @@ -113,7 +113,7 @@ class Outline : public PipelineTask { context.drawRenderers(filter, CommandBuffer::RAYCAST); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combineMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combineMaterial); buffer->endDebugMarker(); } @@ -269,6 +269,7 @@ class GridRender : public PipelineTask { rot = Quaternion(Vector3(1, 0, 0), 90.0f); } + m_grid->setTransform(Matrix4(pos, rot, m_scale), 0); m_grid->setBool("ortho", &ortho); m_grid->setFloat("scale", &m_scale); m_grid->setFloat("width", &width); @@ -279,7 +280,7 @@ class GridRender : public PipelineTask { buffer->beginDebugMarker("GridRender"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(Matrix4(pos, rot, m_scale), m_plane, 0, CommandBuffer::TRANSLUCENT, *m_grid); + buffer->drawMesh(m_plane, 0, CommandBuffer::TRANSLUCENT, *m_grid); buffer->endDebugMarker(); } @@ -402,7 +403,7 @@ class DebugRender : public PipelineTask { int i = 0; for(auto &it : m_buffers) { - it.second->setTexture("texture0", context.textureBuffer(it.first)); + it.second->setTexture("mainTexture", context.textureBuffer(it.first)); float width = 0.5f; float height = 0.5f; @@ -416,7 +417,9 @@ class DebugRender : public PipelineTask { m.mat[12] = width * 0.5f + (i - 4) * width - 1.0f; m.mat[13] = 1.0f - height * 0.5f; } - buffer->drawMesh(m, m_mesh, 0, CommandBuffer::UI, *it.second); + it.second->setTransform(m, 0); + + buffer->drawMesh(m_mesh, 0, CommandBuffer::UI, *it.second); i++; } diff --git a/engine/src/engine.cpp b/engine/src/engine.cpp index 431232dac..8c9f799d1 100644 --- a/engine/src/engine.cpp +++ b/engine/src/engine.cpp @@ -177,7 +177,7 @@ Engine::Engine(File *file, const char *path) { TileSet::registerClassFactory(m_resourceSystem); TileMap::registerClassFactory(m_resourceSystem); - ParticleEffect::registerSuper(m_resourceSystem); + ParticleEffect::registerClassFactory(m_resourceSystem); AnimationStateMachine::registerSuper(m_resourceSystem); diff --git a/engine/src/gizmos.cpp b/engine/src/gizmos.cpp index 0989ad9c7..93f8d371a 100644 --- a/engine/src/gizmos.cpp +++ b/engine/src/gizmos.cpp @@ -8,8 +8,6 @@ #include "commandbuffer.h" -#define OVERRIDE "mainTexture" - Mesh *Gizmos::s_wire = nullptr; Mesh *Gizmos::s_solid = nullptr; @@ -83,7 +81,7 @@ void Gizmos::clear() { void Gizmos::drawSpriteBatch(CommandBuffer *buffer) { for(auto &it : s_sprites) { if(!it.second.mesh->isEmpty()) { - buffer->drawMesh(Matrix4(), it.second.mesh, 0, CommandBuffer::TRANSLUCENT, *it.second.material); + buffer->drawMesh(it.second.mesh, 0, CommandBuffer::TRANSLUCENT, *it.second.material); } } } @@ -93,7 +91,7 @@ void Gizmos::drawSpriteBatch(CommandBuffer *buffer) { */ void Gizmos::drawSolidBatch(CommandBuffer *buffer) { if(!s_solid->isEmpty()) { - buffer->drawMesh(Matrix4(), s_solid, 0, CommandBuffer::TRANSLUCENT, *s_solidMaterial); + buffer->drawMesh(s_solid, 0, CommandBuffer::TRANSLUCENT, *s_solidMaterial); } } /*! @@ -102,7 +100,7 @@ void Gizmos::drawSolidBatch(CommandBuffer *buffer) { */ void Gizmos::drawWireBatch(CommandBuffer *buffer) { if(!s_wire->isEmpty()) { - buffer->drawMesh(Matrix4(), s_wire, 0, CommandBuffer::TRANSLUCENT, *s_wireMaterial); + buffer->drawMesh(s_wire, 0, CommandBuffer::TRANSLUCENT, *s_wireMaterial); } } /*! @@ -166,7 +164,9 @@ void Gizmos::drawIcon(const Vector3 ¢er, const Vector2 &size, const string & batch.mesh->makeDynamic(); batch.mesh->batchMesh(mesh, &q); batch.material = s_spriteMaterial->createInstance(); - batch.material->setTexture(OVERRIDE, Engine::loadResource(name)); + Vector4 color(1.0f); + batch.material->setVector4("mainColor", &color); + batch.material->setTexture("mainTexture", Engine::loadResource(name)); s_sprites[name] = batch; } } diff --git a/engine/src/pipelinecontext.cpp b/engine/src/pipelinecontext.cpp index 45399eb69..cef1d4fa0 100644 --- a/engine/src/pipelinecontext.cpp +++ b/engine/src/pipelinecontext.cpp @@ -97,7 +97,7 @@ void PipelineContext::draw(Camera *camera) { // Finish m_buffer->setRenderTarget(m_defaultTarget); m_buffer->clearRenderTarget(); - m_buffer->drawMesh(Matrix4(), defaultPlane(), 0, CommandBuffer::UI, *m_finalMaterial); + m_buffer->drawMesh(defaultPlane(), 0, CommandBuffer::UI, *m_finalMaterial); } /*! Sets the current \a camera and updates associated matrices in the command buffer. diff --git a/engine/src/pipelinetasks/ambientocclusion.cpp b/engine/src/pipelinetasks/ambientocclusion.cpp index 1f81f42a2..7a64b117a 100644 --- a/engine/src/pipelinetasks/ambientocclusion.cpp +++ b/engine/src/pipelinetasks/ambientocclusion.cpp @@ -129,14 +129,14 @@ void AmbientOcclusion::exec(PipelineContext &context) { buffer->setViewport(0, 0, m_outputs.front().second->width(), m_outputs.front().second->height()); buffer->setRenderTarget(m_ssaoTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_occlusion); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_occlusion); } if(m_blur) { buffer->setViewport(0, 0, m_outputs.back().second->width(), m_outputs.back().second->height()); buffer->setRenderTarget(m_blurTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_blur); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_blur); } if(m_combine) { @@ -146,7 +146,7 @@ void AmbientOcclusion::exec(PipelineContext &context) { } buffer->setRenderTarget(m_combineTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combine); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combine); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/antialiasing.cpp b/engine/src/pipelinetasks/antialiasing.cpp index 181d65305..18d3ec02b 100644 --- a/engine/src/pipelinetasks/antialiasing.cpp +++ b/engine/src/pipelinetasks/antialiasing.cpp @@ -44,7 +44,7 @@ void AntiAliasing::exec(PipelineContext &context) { buffer->beginDebugMarker("AntiAliasing"); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_material); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_material); buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/bloom.cpp b/engine/src/pipelinetasks/bloom.cpp index 7002c548d..408969037 100644 --- a/engine/src/pipelinetasks/bloom.cpp +++ b/engine/src/pipelinetasks/bloom.cpp @@ -106,7 +106,7 @@ void Bloom::exec(PipelineContext &context) { buffer->setRenderTarget(m_bloomPasses[i].downTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].downMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].downMaterial); } buffer->setViewport(0, 0, texture->width(), texture->height()); @@ -118,10 +118,10 @@ void Bloom::exec(PipelineContext &context) { for(uint8_t i = 0; i < BLOOM_PASSES; i++) { buffer->setRenderTarget(m_blurTempTarget); buffer->clearRenderTarget(true, Vector4(0.0f), false, 1.0f); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialH); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialH); buffer->setRenderTarget(m_resultTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialV); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_bloomPasses[i].blurMaterialV); } buffer->endDebugMarker(); diff --git a/engine/src/pipelinetasks/deferredlighting.cpp b/engine/src/pipelinetasks/deferredlighting.cpp index 56a49c0d4..83011ecca 100644 --- a/engine/src/pipelinetasks/deferredlighting.cpp +++ b/engine/src/pipelinetasks/deferredlighting.cpp @@ -38,22 +38,21 @@ void DeferredLighting::exec(PipelineContext &context) { Mesh *mesh = PipelineContext::defaultCube(); - Matrix4 mat; switch(light->lightType()) { case BaseLight::AreaLight: { - Matrix4 m = light->transform()->worldTransform(); + auto instance = light->material(); + if(instance) { + Matrix4 m = light->transform()->worldTransform(); - Vector3 position(m[12], m[13], m[14]); + Vector3 position(m[12], m[13], m[14]); - float d = static_cast(light)->radius() * 2.0f; - mat = Matrix4(position, Quaternion(), Vector3(d)); + float d = static_cast(light)->radius() * 2.0f; - auto instance = light->material(); - if(instance) { Vector3 direction(m.rotation() * Vector3(0.0f, 0.0f, 1.0f)); Vector3 right(m.rotation() * Vector3(1.0f, 0.0f, 0.0f)); Vector3 up(m.rotation() * Vector3(0.0f, 1.0f, 0.0f)); + instance->setTransform(Matrix4(position, Quaternion(), Vector3(d)), 0); instance->setVector3(uniPosition, &position); instance->setVector3(uniDirection, &direction); instance->setVector3(uniRight, &right); @@ -61,38 +60,39 @@ void DeferredLighting::exec(PipelineContext &context) { } } break; case BaseLight::PointLight: { - Matrix4 m = light->transform()->worldTransform(); - - float d = static_cast(light)->attenuationRadius() * 2.0f; - mat = Matrix4(Vector3(m[12], m[13], m[14]), Quaternion(), Vector3(d)); - auto instance = light->material(); if(instance) { + Matrix4 m = light->transform()->worldTransform(); + + float d = static_cast(light)->attenuationRadius() * 2.0f; + Vector3 position(m[12], m[13], m[14]); Vector3 direction(m.rotation() * Vector3(0.0f, 1.0f, 0.0f)); + instance->setTransform(Matrix4(Vector3(m[12], m[13], m[14]), Quaternion(), Vector3(d)), 0); instance->setVector3(uniPosition, &position); instance->setVector3(uniDirection, &direction); } } break; case BaseLight::SpotLight: { - Transform *t = light->transform(); + auto instance = light->material(); + if(instance) { + Transform *t = light->transform(); - Matrix4 m(t->worldTransform()); - Quaternion q(t->worldQuaternion()); + Matrix4 m(t->worldTransform()); + Quaternion q(t->worldQuaternion()); - Vector3 position(m[12], m[13], m[14]); - Vector3 direction(q * Vector3(0.0f, 0.0f, 1.0f)); + Vector3 position(m[12], m[13], m[14]); + Vector3 direction(q * Vector3(0.0f, 0.0f, 1.0f)); - float distance = static_cast(light)->attenuationDistance(); - float angle = static_cast(light)->outerAngle(); - float radius = tan(DEG2RAD * angle * 0.5f) * distance; - mat = Matrix4(position - direction * distance * 0.5f, - q, - Vector3(radius * 2.0f, radius * 2.0f, distance)); + float distance = static_cast(light)->attenuationDistance(); + float angle = static_cast(light)->outerAngle(); + float radius = tan(DEG2RAD * angle * 0.5f) * distance; + Matrix4 mat(position - direction * distance * 0.5f, + q, + Vector3(radius * 2.0f, radius * 2.0f, distance)); - auto instance = light->material(); - if(instance) { + instance->setTransform(mat, 0); instance->setVector3(uniPosition, &position); instance->setVector3(uniDirection, &direction); } @@ -111,7 +111,7 @@ void DeferredLighting::exec(PipelineContext &context) { default: break; } - buffer->drawMesh(mat, mesh, 0, CommandBuffer::LIGHT, *light->material()); + buffer->drawMesh(mesh, 0, CommandBuffer::LIGHT, *light->material()); } buffer->endDebugMarker(); } diff --git a/engine/src/pipelinetasks/reflections.cpp b/engine/src/pipelinetasks/reflections.cpp index 1b185a1ae..f0f2177ea 100644 --- a/engine/src/pipelinetasks/reflections.cpp +++ b/engine/src/pipelinetasks/reflections.cpp @@ -61,13 +61,13 @@ void Reflections::exec(PipelineContext &context) { if(m_slrMaterial) { // sslr step buffer->setRenderTarget(m_slrTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_slrMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_slrMaterial); } if(m_combineMaterial) { // combine step buffer->setRenderTarget(m_combineTarget); - buffer->drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combineMaterial); + buffer->drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::UI, *m_combineMaterial); } buffer->endDebugMarker(); diff --git a/engine/src/resources/material.cpp b/engine/src/resources/material.cpp index 4ed0add97..86ea0b0f8 100644 --- a/engine/src/resources/material.cpp +++ b/engine/src/resources/material.cpp @@ -1,6 +1,8 @@ #include "resources/material.h" #include "resources/texture.h" +#include "commandbuffer.h" + #include namespace { @@ -24,6 +26,7 @@ namespace { MaterialInstance::MaterialInstance(Material *material) : m_material(material), + m_instanceCount(1), m_surfaceType(0), m_uniformDirty(true) { @@ -32,6 +35,7 @@ MaterialInstance::MaterialInstance(Material *material) : MaterialInstance::~MaterialInstance() { } + /*! Getter for the base material associated with the instance. */ @@ -48,6 +52,23 @@ Texture *MaterialInstance::texture(const char *name) { } return nullptr; } +/*! + Returns the number of GPU instances to be rendered. +*/ +uint32_t MaterialInstance::instanceCount() const { + return m_instanceCount; +} +/*! + Sets the \a number of GPU instances to be rendered. +*/ +void MaterialInstance::setInstanceCount(uint32_t number) { + m_instanceCount = number; + + uint32_t istanceBufferSize = m_instanceCount * m_material->m_uniformSize; + if(m_uniformBuffer.size() < istanceBufferSize) { + m_uniformBuffer.resize(istanceBufferSize); + } +} /*! Sets a boolean parameter with optional array support. Parameter \a name specifies a name of the boolean parameter. @@ -162,16 +183,6 @@ void MaterialInstance::setVector4(const char *name, const Vector4 *value, int32_ setBufferValue(name, value); } -/*! - Sets the \a transform matrix for the object. -*/ -void MaterialInstance::setTransform(const Matrix4 &tranform) { - if(m_uniformBuffer.size() < m_material->m_uniformSize) { - m_uniformBuffer.resize(m_material->m_uniformSize); - } - memcpy(m_uniformBuffer.data(), &tranform, sizeof(Matrix4)); - m_uniformDirty = true; -} /*! Sets a Matrix4 parameter with optional array support. Parameter \a name specifies a name of the Matrix4 parameter. @@ -191,6 +202,24 @@ void MaterialInstance::setMatrix4(const char *name, const Matrix4 *value, int32_ setBufferValue(name, value); } +/*! + Encodes the \a transform matrix and object id for the object. +*/ +void MaterialInstance::setTransform(const Matrix4 &transform, uint32_t id) { + if(m_uniformBuffer.size() < m_material->m_uniformSize) { + m_uniformBuffer.resize(m_material->m_uniformSize); + } + + Matrix4 m(transform); + Vector4 color(CommandBuffer::idToColor(id)); + m[3] = color.x; + m[7] = color.y; + m[11] = color.z; + m[15] = color.w; + + memcpy(m_uniformBuffer.data(), &m, sizeof(Matrix4)); + m_uniformDirty = true; +} /*! Sets the \a value of a parameter with specified \a name in the uniform buffer. */ @@ -200,6 +229,7 @@ void MaterialInstance::setBufferValue(const char *name, const void *value) { if(m_uniformBuffer.size() < m_material->m_uniformSize) { m_uniformBuffer.resize(m_material->m_uniformSize); } + memcpy(&m_uniformBuffer[it.offset], value, it.size); m_uniformDirty = true; break; @@ -212,6 +242,15 @@ void MaterialInstance::setBufferValue(const char *name, const void *value) { void MaterialInstance::setTexture(const char *name, Texture *texture) { m_textureOverride[name] = texture; } +/*! + Returns a reference to CPU part of uniform buffer. + Developer can modify it for their needs. + Marks buffer as dirty. +*/ +vector &MaterialInstance::rawUniformBuffer() { + m_uniformDirty = true; + return m_uniformBuffer; +} /*! Gets the total count of parameters in the material. */ @@ -396,11 +435,10 @@ void Material::loadUserData(const VariantMap &data) { } } { - m_uniformSize = sizeof(Matrix4); + size_t offset = sizeof(Matrix4); m_uniforms.clear(); auto it = data.find(gUniforms); if(it != data.end()) { - size_t offset = m_uniformSize; VariantList uniforms = (*it).second.toList(); m_uniforms.resize(uniforms.size()); int i = 0; @@ -419,8 +457,8 @@ void Material::loadUserData(const VariantMap &data) { i++; } - m_uniformSize = offset; } + m_uniformSize = offset; } { m_attributes.clear(); @@ -559,5 +597,6 @@ void Material::initInstance(MaterialInstance *instance) { default: break; } } + instance->setTransform(Matrix4(), 0); } } diff --git a/engine/src/resources/particleeffect.cpp b/engine/src/resources/particleeffect.cpp index 60681864e..392e3e703 100644 --- a/engine/src/resources/particleeffect.cpp +++ b/engine/src/resources/particleeffect.cpp @@ -65,119 +65,6 @@ void ParticleModificator::loadData(const VariantList &list) { Users can customize these settings, such as associating a mesh and material, defining distribution factors, enabling GPU simulation, setting local or world space, specifying continuous or discrete emission, and applying particle modifiers. */ -ParticleEmitter::ParticleEmitter() : - m_mesh(nullptr), - m_material(nullptr), - m_distibution(1.0f), - m_gpu(false), - m_local(false), - m_continous(true) { - -} -/*! - Equality operator for comparing two particle \a emitter objects. - Returns true if the emitters are equal, false otherwise. -*/ -bool ParticleEmitter::operator== (const ParticleEmitter &emitter) const { - return (m_mesh == emitter.m_mesh) && - (m_material == emitter.m_material) && - (m_distibution == emitter.m_distibution) && - (m_gpu == emitter.m_gpu) && - (m_local == emitter.m_local) && - (m_continous == emitter.m_continous); -} -/*! - Getter for the mesh associated with the particle emitter. -*/ -Mesh *ParticleEmitter::mesh() const { - return m_mesh; -} -/*! - Setter for the \a mesh associated with the particle emitter. -*/ -void ParticleEmitter::setMesh(Mesh *mesh) { - m_mesh = mesh; -} -/*! - Getter for the material associated with the particle emitter. -*/ -Material *ParticleEmitter::material() const { - return m_material; -} -/*! - Setter for the \a material associated with the particle emitter. -*/ -void ParticleEmitter::setMaterial(Material *material) { - m_material = material; -} -/*! - Getter for the distribution factor of emitted particles. -*/ -float ParticleEmitter::distribution() const { - return m_distibution; -} -/*! - Setter for the \a distribution factor of emitted particles. -*/ -void ParticleEmitter::setDistribution(float distribution) { - m_distibution = distribution; -} -/*! - Getter for the local flag indicating local particle space. - Returns true if particles are in local space, false otherwise. -*/ -bool ParticleEmitter::local() const { - return m_local; -} -/*! - Setter for the \a local flag indicating local particle space. -*/ -void ParticleEmitter::setLocal(bool local) { - m_local = local; -} -/*! - Getter for the GPU flag indicating GPU particle simulation. - Returns true if GPU particle simulation is enabled, false otherwise. - - \note Gpu simulation is not supported yet. -*/ -bool ParticleEmitter::gpu() const { - return m_gpu; -} -/*! - Setter for the \a gpu flag indicating GPU particle simulation. - - \note Gpu simulation is not supported yet. -*/ -void ParticleEmitter::setGpu(bool gpu) { - m_gpu = gpu; -} -/*! - Getter for the continuous flag indicating continuous particle emission. - Returns true for continuous emission, false for one time emission. -*/ -bool ParticleEmitter::continous() const { - return m_continous; -} -/*! - Setter for the \a continuous flag indicating continuous particle emission. -*/ -void ParticleEmitter::setContinous(bool continuous) { - m_continous = continuous; -} -/*! - Getter for the deque of particle modifiers. -*/ -ModifiersDeque &ParticleEmitter::modifiers() { - return m_modifiers; -} -/*! - Setter for the deque of particle \a modifiers. -*/ -void ParticleEmitter::setModifiers(const ModifiersDeque &modifiers) { - m_modifiers = modifiers; -} - ParticleData::ParticleData() : color(1.0f), colrate(0.0f), @@ -390,7 +277,13 @@ class Velocity: public ParticleModificator { PartcileEffect alows developer to create or modify a complex particle effects. */ -ParticleEffect::ParticleEffect() { +ParticleEffect::ParticleEffect() : + m_mesh(nullptr), + m_material(nullptr), + m_distibution(1.0f), + m_gpu(false), + m_local(false), + m_continous(true) { PROFILE_FUNCTION(); } @@ -399,99 +292,148 @@ ParticleEffect::~ParticleEffect() { PROFILE_FUNCTION(); } /*! - Removes all emitters from the effect + Getter for the mesh associated with the particle emitter. */ -void ParticleEffect::clear() { - m_Emitters.clear(); +Mesh *ParticleEffect::mesh() const { + return m_mesh; } /*! - Returns a count of the emitters for effect. + Setter for the \a mesh associated with the particle emitter. */ -int ParticleEffect::emittersCount() const { - PROFILE_FUNCTION(); - return m_Emitters.size(); +void ParticleEffect::setMesh(Mesh *mesh) { + m_mesh = mesh; } /*! - Returns an emitter with \a index. + Getter for the material associated with the particle emitter. */ -ParticleEmitter *ParticleEffect::emitter(int index) { - PROFILE_FUNCTION(); - return &m_Emitters[index]; +Material *ParticleEffect::material() const { + return m_material; } /*! - Adds an \a emitter to the effect. + Setter for the \a material associated with the particle emitter. */ -void ParticleEffect::addEmitter(ParticleEmitter *emitter) { - if(emitter) { - m_Emitters.push_back(*emitter); - } +void ParticleEffect::setMaterial(Material *material) { + m_material = material; +} +/*! + Getter for the distribution factor of emitted particles. +*/ +float ParticleEffect::distribution() const { + return m_distibution; +} +/*! + Setter for the \a distribution factor of emitted particles. +*/ +void ParticleEffect::setDistribution(float distribution) { + m_distibution = distribution; +} +/*! + Getter for the local flag indicating local particle space. + Returns true if particles are in local space, false otherwise. +*/ +bool ParticleEffect::local() const { + return m_local; +} +/*! + Setter for the \a local flag indicating local particle space. +*/ +void ParticleEffect::setLocal(bool local) { + m_local = local; +} +/*! + Getter for the GPU flag indicating GPU particle simulation. + Returns true if GPU particle simulation is enabled, false otherwise. + + \note Gpu simulation is not supported yet. +*/ +bool ParticleEffect::gpu() const { + return m_gpu; +} +/*! + Setter for the \a gpu flag indicating GPU particle simulation. + + \note Gpu simulation is not supported yet. +*/ +void ParticleEffect::setGpu(bool gpu) { + m_gpu = gpu; +} +/*! + Getter for the continuous flag indicating continuous particle emission. + Returns true for continuous emission, false for one time emission. +*/ +bool ParticleEffect::continous() const { + return m_continous; +} +/*! + Setter for the \a continuous flag indicating continuous particle emission. +*/ +void ParticleEffect::setContinous(bool continuous) { + m_continous = continuous; +} +/*! + Getter for the deque of particle modifiers. +*/ +ModifiersDeque &ParticleEffect::modifiers() { + return m_modifiers; +} +/*! + Setter for the deque of particle \a modifiers. +*/ +void ParticleEffect::setModifiers(const ModifiersDeque &modifiers) { + m_modifiers = modifiers; } /*! \internal */ void ParticleEffect::loadUserData(const VariantMap &data) { PROFILE_FUNCTION(); - clear(); - { - auto section = data.find(gEmitters); - if(section != data.end()) { - VariantList list = (*section).second.value(); - for(auto &e : list) { - VariantList fields = e.value(); - auto it = fields.begin(); - ParticleEmitter emitter; - - emitter.setMesh(Engine::loadResource((*it).toString())); - it++; - emitter.setMaterial(Engine::loadResource((*it).toString())); - it++; - emitter.setGpu((*it).toBool()); - it++; - emitter.setLocal((*it).toBool()); - it++; - emitter.setContinous((*it).toBool()); - it++; - emitter.setDistribution((*it).toFloat()); - it++; - - for(auto &m : (*it).value()) { - VariantList mods = m.value(); - auto mod = mods.begin(); - int32_t type = (*mod).toInt(); - - ParticleModificator *modificator = nullptr; - switch (type) { - case ParticleModificator::LIFETIME: modificator = new Lifetime(); break; - case ParticleModificator::STARTSIZE: modificator = new StartSize(); break; - case ParticleModificator::STARTCOLOR: modificator = new StartColor(); break; - case ParticleModificator::STARTANGLE: modificator = new StartAngle(); break; - case ParticleModificator::STARTPOSITION: modificator = new StartPosition(); break; - - case ParticleModificator::SCALESIZE: modificator = new ScaleSize(); break; - case ParticleModificator::SCALECOLOR: modificator = new ScaleColor(); break; - case ParticleModificator::SCALEANGLE: modificator = new ScaleAngle(); break; - case ParticleModificator::VELOCITY: modificator = new Velocity(); break; - default: break; - } - - if(modificator) { - mod++; - modificator->loadData((*mod).value()); - emitter.modifiers().push_back(modificator); - } + + auto section = data.find(gEmitters); + if(section != data.end()) { + VariantList list = (*section).second.value(); + for(auto &e : list) { + VariantList fields = e.value(); + auto it = fields.begin(); + + setMesh(Engine::loadResource((*it).toString())); + it++; + setMaterial(Engine::loadResource((*it).toString())); + it++; + setGpu((*it).toBool()); + it++; + setLocal((*it).toBool()); + it++; + setContinous((*it).toBool()); + it++; + setDistribution((*it).toFloat()); + it++; + + for(auto &m : (*it).value()) { + VariantList mods = m.value(); + auto mod = mods.begin(); + int32_t type = (*mod).toInt(); + + ParticleModificator *modificator = nullptr; + switch (type) { + case ParticleModificator::LIFETIME: modificator = new Lifetime(); break; + case ParticleModificator::STARTSIZE: modificator = new StartSize(); break; + case ParticleModificator::STARTCOLOR: modificator = new StartColor(); break; + case ParticleModificator::STARTANGLE: modificator = new StartAngle(); break; + case ParticleModificator::STARTPOSITION: modificator = new StartPosition(); break; + + case ParticleModificator::SCALESIZE: modificator = new ScaleSize(); break; + case ParticleModificator::SCALECOLOR: modificator = new ScaleColor(); break; + case ParticleModificator::SCALEANGLE: modificator = new ScaleAngle(); break; + case ParticleModificator::VELOCITY: modificator = new Velocity(); break; + default: break; } - m_Emitters.push_back(emitter); + if(modificator) { + mod++; + modificator->loadData((*mod).value()); + m_modifiers.push_back(modificator); + } } } } } -/*! - \internal - - \warning Do not call this function manually -*/ -void ParticleEffect::registerSuper(ObjectSystem *system) { - REGISTER_META_TYPE(ParticleEmitter); - ParticleEffect::registerClassFactory(system); -} diff --git a/engine/src/resources/tilemap.cpp b/engine/src/resources/tilemap.cpp index 865f63263..90fec6e3f 100644 --- a/engine/src/resources/tilemap.cpp +++ b/engine/src/resources/tilemap.cpp @@ -186,14 +186,19 @@ void TileMap::refreshAllTiles() const { m_tileMesh->clear(); + uint32_t size = m_width * m_height; + Vector3Vector vertices; - vertices.resize(m_width * m_height * 4); + vertices.resize(size * 4); Vector2Vector uvs; - uvs.resize(m_width * m_height * 4); + uvs.resize(size * 4); + + Vector4Vector colors; + colors.resize(size * 4, Vector4(1.0f)); IndexVector indices; - indices.reserve(m_width * m_height * 6); + indices.reserve(size * 6); Vector2 offset; switch(m_orientation) { @@ -286,6 +291,7 @@ void TileMap::refreshAllTiles() const { m_tileMesh->clear(); m_tileMesh->setUv0(uvs); + m_tileMesh->setColors(colors); m_tileMesh->setVertices(vertices); m_tileMesh->setIndices(indices); m_tileMesh->recalcBounds(); diff --git a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp index a87cafdf1..501e1bfd1 100644 --- a/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp +++ b/modules/editor/grapheditor/editor/graph/graphwidgets/linksrender.cpp @@ -36,9 +36,10 @@ void LinksRender::setGraph(AbstractNodeGraph *graph) { \internal */ void LinksRender::draw(CommandBuffer &buffer) { + m_material->setTransform(rectTransform()->worldTransform(), 0); + if(m_linksMesh && !m_linksMesh->vertices().empty()) { - buffer.drawMesh(rectTransform()->worldTransform(), - m_linksMesh, 0, CommandBuffer::UI, *m_material); + buffer.drawMesh(m_linksMesh, 0, CommandBuffer::UI, *m_material); } if(m_creationMesh && m_portWidget) { Vector3Vector vertices; @@ -76,8 +77,7 @@ void LinksRender::draw(CommandBuffer &buffer) { m_creationMesh->recalcBounds(); } - buffer.drawMesh(rectTransform()->worldTransform(), - m_creationMesh, 0, CommandBuffer::UI, *m_material); + buffer.drawMesh(m_creationMesh, 0, CommandBuffer::UI, *m_material); } } diff --git a/modules/editor/shadertools/converter/functions/customfunction.h b/modules/editor/shadertools/converter/functions/customfunction.h index c6289ee5b..404ede1fe 100644 --- a/modules/editor/shadertools/converter/functions/customfunction.h +++ b/modules/editor/shadertools/converter/functions/customfunction.h @@ -129,7 +129,7 @@ class CustomFunction : public ShaderNode { int32_t build(QString &code, QStack &stack, const AbstractNodeGraph::Link &link, int32_t &depth, int32_t &type) override { if(m_position == -1) { if(!m_func.isEmpty()) { - static_cast(m_graph)->addFunction(m_funcName, m_func); + static_cast(m_graph)->addFunction(m_funcName, m_func); if(link.oport->m_type != QMetaType::Void) { type = link.oport->m_type; diff --git a/modules/editor/shadertools/converter/functions/function.h b/modules/editor/shadertools/converter/functions/function.h index ecf1ef647..e409aa30e 100644 --- a/modules/editor/shadertools/converter/functions/function.h +++ b/modules/editor/shadertools/converter/functions/function.h @@ -1,7 +1,7 @@ #ifndef FUNCTION_H #define FUNCTION_H -#include "../shadernodegraph.h" +#include "../shadergraph.h" #include #include @@ -272,7 +272,7 @@ class ShaderNode : public GraphNode { } protected: - friend class ShaderNodeGraph; + friend class ShaderGraph; list> m_inputs; list> m_outputs; diff --git a/modules/editor/shadertools/converter/functions/materialparam.h b/modules/editor/shadertools/converter/functions/materialparam.h index 33deda795..8e8fd8ddd 100644 --- a/modules/editor/shadertools/converter/functions/materialparam.h +++ b/modules/editor/shadertools/converter/functions/materialparam.h @@ -24,7 +24,7 @@ class ParamFloat : public ShaderNode { if(type == 0) { type = link.oport->m_type; } - static_cast(m_graph)->addUniform(objectName(), type, m_defaultValue); + static_cast(m_graph)->addUniform(objectName(), type, m_defaultValue); stack.push(QString("uni.%1").arg(objectName())); return ShaderNode::build(code, stack, link, depth, type); @@ -67,7 +67,7 @@ class ParamVector : public ShaderNode { if(type == 0) { type = link.oport->m_type; } - static_cast(m_graph)->addUniform(objectName(), type, QVector4D(m_defaultValue.x, + static_cast(m_graph)->addUniform(objectName(), type, QVector4D(m_defaultValue.x, m_defaultValue.y, m_defaultValue.z, m_defaultValue.z)); diff --git a/modules/editor/shadertools/converter/functions/matrixoperations.h b/modules/editor/shadertools/converter/functions/matrixoperations.h index 7c08c3bf8..17d30d9ad 100644 --- a/modules/editor/shadertools/converter/functions/matrixoperations.h +++ b/modules/editor/shadertools/converter/functions/matrixoperations.h @@ -149,7 +149,7 @@ class ExtractPosition : public ShaderNode { " return vec4(m[3][0], m[3][1], m[3][2], m[3][3]);\n" "}\n"; - static_cast(m_graph)->addFunction("ExtractPosition", func); + static_cast(m_graph)->addFunction("ExtractPosition", func); QStringList arguments = getArguments(code, stack, depth, type); diff --git a/modules/editor/shadertools/converter/functions/texturesample.h b/modules/editor/shadertools/converter/functions/texturesample.h index 16302228e..e1fb6df94 100644 --- a/modules/editor/shadertools/converter/functions/texturesample.h +++ b/modules/editor/shadertools/converter/functions/texturesample.h @@ -75,7 +75,7 @@ class TextureObject : public TextureFunction { } int32_t build(QString &code, QStack &stack,const AbstractNodeGraph::Link &link, int32_t &depth, int32_t &type) override { - int result = static_cast(m_graph)->addTexture(m_path.path, m_sub, false); + int result = static_cast(m_graph)->addTexture(m_path.path, m_sub, false); if(result < 0) { m_graph->reportMessage(this, "Missing texture"); return -1; @@ -119,7 +119,7 @@ class TextureSample : public TextureFunction { } int32_t build(QString &code, QStack &stack,const AbstractNodeGraph::Link &link, int32_t &depth, int32_t &type) override { - int result = static_cast(m_graph)->addTexture(m_path.path, m_sub, false); + int result = static_cast(m_graph)->addTexture(m_path.path, m_sub, false); if(result < 0) { m_graph->reportMessage(this, "Missing texture"); return -1; @@ -161,7 +161,7 @@ class RenderTargetSample : public TextureFunction { } int32_t build(QString &code, QStack &stack,const AbstractNodeGraph::Link &link, int32_t &depth, int32_t &type) override { - static_cast(m_graph)->addTexture(m_name, m_sub, ShaderRootNode::Target); + static_cast(m_graph)->addTexture(m_name, m_sub, ShaderRootNode::Target); return TextureFunction::build(code, stack, link, depth, type); } @@ -193,7 +193,7 @@ class TextureSampleCube : public TextureSample { } int32_t build(QString &code, QStack &stack,const AbstractNodeGraph::Link &link, int32_t &depth, int32_t &type) override { - int result = static_cast(m_graph)->addTexture(m_path.path, m_sub, ShaderRootNode::Cube); + int result = static_cast(m_graph)->addTexture(m_path.path, m_sub, ShaderRootNode::Cube); if(result < 0) { m_graph->reportMessage(this, "Missing texture"); return -1; diff --git a/modules/editor/shadertools/converter/shaderbuilder.cpp b/modules/editor/shadertools/converter/shaderbuilder.cpp index c1c09fa3b..61248220f 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.cpp +++ b/modules/editor/shadertools/converter/shaderbuilder.cpp @@ -22,7 +22,14 @@ #include -#define FORMAT_VERSION 12 +#define FORMAT_VERSION 13 + +enum ShaderFlags { + Compute = (1<<0), + Static = (1<<1), + Skinned = (1<<2), + Particle = (1<<3) +}; namespace { const char *gValue("value"); @@ -133,10 +140,14 @@ void ShaderBuilder::buildInstanceData(const VariantMap &user, PragmaMap &pragmas string result; string modelMatrix = - " mat4 modelMatrix = mat4(instance.data[_instanceOffset + 0]," - " instance.data[_instanceOffset + 1]," - " instance.data[_instanceOffset + 2]," - " instance.data[_instanceOffset + 3]);\n"; + " mat4 modelMatrix = mat4(vec4(instance.data[_instanceOffset + 0].xyz, 0.0f),\n" + " vec4(instance.data[_instanceOffset + 1].xyz, 0.0f),\n" + " vec4(instance.data[_instanceOffset + 2].xyz, 0.0f),\n" + " vec4(instance.data[_instanceOffset + 3].xyz, 1.0f));\n" + " vec4 objectId = vec4(instance.data[_instanceOffset + 0].w,\n" + " instance.data[_instanceOffset + 1].w,\n" + " instance.data[_instanceOffset + 2].w,\n" + " instance.data[_instanceOffset + 3].w);"; int offset = 4; @@ -263,7 +274,7 @@ AssetConverter::ReturnCode ShaderBuilder::convertFile(AssetConverterSettings *se QFileInfo info(builderSettings->source()); if(info.suffix() == "mtl") { - ShaderNodeGraph nodeGraph; + ShaderGraph nodeGraph; nodeGraph.load(builderSettings->source()); if(nodeGraph.buildGraph()) { if(builderSettings->currentVersion() != builderSettings->version()) { @@ -274,7 +285,7 @@ AssetConverter::ReturnCode ShaderBuilder::convertFile(AssetConverterSettings *se } else if(info.suffix() == "shader") { parseShaderFormat(builderSettings->source(), data); } else if(info.suffix() == "compute") { - parseShaderFormat(builderSettings->source(), data, true); + parseShaderFormat(builderSettings->source(), data, Compute); } if(data.empty()) { @@ -387,7 +398,7 @@ Variant ShaderBuilder::compile(ShaderBuilderSettings::Rhi rhi, const string &buf return data; } -bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, bool compute) { +bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, int flags) { QFile file(path); if(file.open(QIODevice::ReadOnly | QIODevice::Text)) { QByteArray data = file.readAll(); @@ -437,10 +448,10 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo PragmaMap pragmas; buildInstanceData(user, pragmas); - if(compute) { + if(flags & Compute) { string str = shaders[gCompute]; if(!str.empty()) { - user[FRAGMENT] = loadShader(str, define, pragmas); + user["Shader"] = loadShader(str, define, pragmas); } } else { if(currentRhi() == ShaderBuilderSettings::Rhi::Vulkan) { @@ -461,6 +472,11 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo user[FRAGMENT] = loadIncludes("Default.frag", define, pragmas); } + Variant data = ShaderBuilder::loadIncludes("Visibility.frag", define, pragmas); + if(data.isValid()) { + user[VISIBILITY] = data; + } + str = shaders[gVertex]; if(!str.empty()) { user[STATIC] = loadShader(str, define, pragmas); @@ -470,6 +486,16 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo file = "Fullscreen.vert"; } user[STATIC] = loadIncludes(file, define, pragmas); + + flags = materialType == Material::Surface ? (Skinned | Particle) : 0; + + if(flags & Skinned) { + user[SKINNED] = loadIncludes("Skinned.vert", define, pragmas); + } + + if(flags & Particle) { + user[PARTICLE] = loadIncludes("Billboard.vert", define, pragmas); + } } str = shaders[gGeometry]; diff --git a/modules/editor/shadertools/converter/shaderbuilder.h b/modules/editor/shadertools/converter/shaderbuilder.h index ac25a3349..9e48d826a 100644 --- a/modules/editor/shadertools/converter/shaderbuilder.h +++ b/modules/editor/shadertools/converter/shaderbuilder.h @@ -3,7 +3,7 @@ #include -#include "shadernodegraph.h" +#include "shadergraph.h" #include "spirvconverter.h" @@ -128,7 +128,7 @@ class ShaderBuilder : public AssetConverter { static Variant compile(ShaderBuilderSettings::Rhi rhi, const string &buff, SpirVConverter::Inputs &inputs, int stage); - bool parseShaderFormat(const QString &path, VariantMap &data, bool compute = false); + bool parseShaderFormat(const QString &path, VariantMap &data, int flags = false); bool saveShaderFormat(const QString &path, const map &shaders, const VariantMap &user); bool parseProperties(const QDomElement &element, VariantMap &user); diff --git a/modules/editor/shadertools/converter/shadernodegraph.cpp b/modules/editor/shadertools/converter/shadergraph.cpp similarity index 91% rename from modules/editor/shadertools/converter/shadernodegraph.cpp rename to modules/editor/shadertools/converter/shadergraph.cpp index e919f8770..fb9c5b993 100644 --- a/modules/editor/shadertools/converter/shadernodegraph.cpp +++ b/modules/editor/shadertools/converter/shadergraph.cpp @@ -1,5 +1,4 @@ - -#include "shadernodegraph.h" +#include "shadergraph.h" #include #include @@ -74,7 +73,7 @@ map ShaderNode::m_portColors = { { QMetaType::QImage, Vector4(0.93f, 0.5f, 0.07f, 1.0f) }, }; -ShaderNodeGraph::ShaderNodeGraph() { +ShaderGraph::ShaderGraph() { m_version = ShaderBuilder::version(); scanForCustomFunctions(); @@ -249,11 +248,11 @@ ShaderNodeGraph::ShaderNodeGraph() { m_previewSettings.setDoubleSided(true); } -ShaderNodeGraph::~ShaderNodeGraph() { +ShaderGraph::~ShaderGraph() { cleanup(); } -void ShaderNodeGraph::scanForCustomFunctions() { +void ShaderGraph::scanForCustomFunctions() { QStringList filter({"*.mtlf"}); QStringList files; @@ -286,7 +285,7 @@ void ShaderNodeGraph::scanForCustomFunctions() { } } -GraphNode *ShaderNodeGraph::nodeCreate(const QString &path, int &index) { +GraphNode *ShaderGraph::nodeCreate(const QString &path, int &index) { const QByteArray className = qPrintable(path + "*"); const int type = QMetaType::type(className); const QMetaObject *meta = QMetaType::metaObjectForType(type); @@ -299,7 +298,7 @@ GraphNode *ShaderNodeGraph::nodeCreate(const QString &path, int &index) { ShaderNode *function = dynamic_cast(node); if(function) { function->createParams(); - connect(function, &ShaderNode::updated, this, &ShaderNodeGraph::onNodeUpdated); + connect(function, &ShaderNode::updated, this, &ShaderGraph::onNodeUpdated); } else { NodeGroup *group = dynamic_cast(node); if(group) { @@ -320,7 +319,7 @@ GraphNode *ShaderNodeGraph::nodeCreate(const QString &path, int &index) { CustomFunction *function = new CustomFunction(); function->exposeFunction(m_exposedFunctions[path]); function->setGraph(this); - connect(function, &ShaderNode::updated, this, &ShaderNodeGraph::onNodeUpdated); + connect(function, &ShaderNode::updated, this, &ShaderGraph::onNodeUpdated); if(index == -1) { index = m_nodes.size(); @@ -335,10 +334,10 @@ GraphNode *ShaderNodeGraph::nodeCreate(const QString &path, int &index) { return nullptr; } -GraphNode *ShaderNodeGraph::createRoot() { +GraphNode *ShaderGraph::createRoot() { ShaderRootNode *result = new ShaderRootNode; result->setGraph(this); - connect(result, &ShaderRootNode::graphUpdated, this, &ShaderNodeGraph::graphUpdated); + connect(result, &ShaderRootNode::graphUpdated, this, &ShaderGraph::graphUpdated); int i = 0; for(auto &it : m_inputs) { @@ -352,7 +351,7 @@ GraphNode *ShaderNodeGraph::createRoot() { return result; } -void ShaderNodeGraph::nodeDelete(GraphNode *node) { +void ShaderGraph::nodeDelete(GraphNode *node) { AbstractNodeGraph::nodeDelete(node); auto it = m_previews.find(node); @@ -365,7 +364,7 @@ void ShaderNodeGraph::nodeDelete(GraphNode *node) { } } -QStringList ShaderNodeGraph::nodeList() const { +QStringList ShaderGraph::nodeList() const { QStringList result; for(auto &it : m_nodeTypes) { const int type = QMetaType::type( qPrintable(it) ); @@ -385,7 +384,7 @@ QStringList ShaderNodeGraph::nodeList() const { return result; } -void ShaderNodeGraph::loadGraphV0(const QVariantMap &data) { +void ShaderGraph::loadGraphV0(const QVariantMap &data) { AbstractNodeGraph::loadGraphV0(data); ShaderRootNode *root = static_cast(m_rootNode); @@ -405,7 +404,7 @@ void ShaderNodeGraph::loadGraphV0(const QVariantMap &data) { emit graphUpdated(); } -void ShaderNodeGraph::loadGraphV11(const QDomElement &parent) { +void ShaderGraph::loadGraphV11(const QDomElement &parent) { AbstractNodeGraph::loadGraphV11(parent); if(parent.tagName() == gUser) { @@ -447,7 +446,7 @@ void ShaderNodeGraph::loadGraphV11(const QDomElement &parent) { } } -void ShaderNodeGraph::saveGraph(QDomElement parent, QDomDocument xml) const { +void ShaderGraph::saveGraph(QDomElement parent, QDomDocument xml) const { AbstractNodeGraph::saveGraph(parent, xml); ShaderRootNode *root = static_cast(m_rootNode); @@ -495,17 +494,17 @@ void ShaderNodeGraph::saveGraph(QDomElement parent, QDomDocument xml) const { parent.appendChild(user); } -void ShaderNodeGraph::loadUserValues(GraphNode *node, const QVariantMap &values) { +void ShaderGraph::loadUserValues(GraphNode *node, const QVariantMap &values) { node->blockSignals(true); node->loadUserData(values); node->blockSignals(false); } -void ShaderNodeGraph::saveUserValues(GraphNode *node, QVariantMap &values) const { +void ShaderGraph::saveUserValues(GraphNode *node, QVariantMap &values) const { node->saveUserData(values); } -bool ShaderNodeGraph::buildGraph(GraphNode *node) { +bool ShaderGraph::buildGraph(GraphNode *node) { if(node == nullptr) { node = m_rootNode; } @@ -562,11 +561,19 @@ bool ShaderNodeGraph::buildGraph(GraphNode *node) { return true; } -VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) { +VariantMap ShaderGraph::data(bool editor, ShaderRootNode *root) { if(root == nullptr) { root = static_cast(m_rootNode); } + Material::BlendState blendState; + blendState.enabled = true; + blendState.sourceColorBlendMode = Material::BlendFactor::One; + blendState.sourceAlphaBlendMode = Material::BlendFactor::One; + + blendState.destinationColorBlendMode = Material::BlendFactor::One; + blendState.destinationAlphaBlendMode = Material::BlendFactor::One; + VariantMap user; VariantList properties; properties.push_back(root->materialType()); @@ -575,9 +582,9 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) { properties.push_back(root->isWireframe()); user[PROPERTIES] = properties; - user[BLENDSTATE] = ShaderBuilder::toVariant(root->blendState()); - user[DEPTHSTATE] = ShaderBuilder::toVariant(root->depthState()); - user[STENCILSTATE] = ShaderBuilder::toVariant(root->stencilState()); + user[BLENDSTATE] = ShaderBuilder::toVariant((root == m_rootNode) ? root->blendState() : blendState); + user[DEPTHSTATE] = ShaderBuilder::toVariant((root == m_rootNode) ? root->depthState() : Material::DepthState()); + user[STENCILSTATE] = ShaderBuilder::toVariant((root == m_rootNode) ? root->stencilState() : Material::StencilState()); VariantList textures; uint16_t i = 0; @@ -617,9 +624,11 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) { Material::BlendState blend = root->blendState(); string define; - define += "\n#define USE_GBUFFER"; + if(root != m_rootNode) { + define += "\n#define USE_GBUFFER"; + } - if(root->lightModel() == ShaderRootNode::Lit) { + if((root == m_rootNode) && root->lightModel() == ShaderRootNode::Lit) { define += "\n#define USE_TBN"; VariantList data; @@ -639,8 +648,7 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) { } } if(root->materialType() == ShaderRootNode::Surface && !editor) { - define += "\n#define VISIBILITY_BUFFER 1"; - Variant data = ShaderBuilder::loadIncludes(file, define, m_pragmas); + Variant data = ShaderBuilder::loadIncludes(file, define + "\n#define VISIBILITY_BUFFER", m_pragmas); if(data.isValid()) { user[VISIBILITY] = data; } @@ -648,7 +656,7 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) { // Vertex shader file = "Static.vert"; - if(root->materialType() == ShaderRootNode::PostProcess) { + if((root != m_rootNode) || root->materialType() == ShaderRootNode::PostProcess) { file = "Fullscreen.vert"; } Variant data = ShaderBuilder::loadIncludes(file, define, m_pragmas); @@ -682,7 +690,7 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) { return user; } -int ShaderNodeGraph::addTexture(const QString &path, Vector4 &sub, int32_t flags) { +int ShaderGraph::addTexture(const QString &path, Vector4 &sub, int32_t flags) { sub = Vector4(0.0f, 0.0f, 1.0f, 1.0f); int index = m_textures.indexOf({ path, flags }); @@ -693,7 +701,7 @@ int ShaderNodeGraph::addTexture(const QString &path, Vector4 &sub, int32_t flags return index; } -void ShaderNodeGraph::addUniform(const QString &name, uint8_t type, const QVariant &value) { +void ShaderGraph::addUniform(const QString &name, uint8_t type, const QVariant &value) { for(auto &it : m_uniforms) { if(it.name == name) { it.type = type; @@ -704,14 +712,14 @@ void ShaderNodeGraph::addUniform(const QString &name, uint8_t type, const QVaria m_uniforms.push_back({name, type, 1, value}); } -void ShaderNodeGraph::addFunction(const QString &name, QString &code) { +void ShaderGraph::addFunction(const QString &name, QString &code) { auto it = m_functions.find(name); if(it == m_functions.end()) { m_functions[name] = code; } } -QString ShaderNodeGraph::buildFrom(GraphNode *node, Stage stage) { +QString ShaderGraph::buildFrom(GraphNode *node, Stage stage) { for(auto &it : m_nodes) { ShaderNode *node = dynamic_cast(it); if(node) { @@ -816,18 +824,18 @@ QString ShaderNodeGraph::buildFrom(GraphNode *node, Stage stage) { return result; } -void ShaderNodeGraph::cleanup() { +void ShaderGraph::cleanup() { m_textures.clear(); m_uniforms.clear(); m_functions.clear(); m_pragmas.clear(); } -void ShaderNodeGraph::setPragma(const string &key, const string &value) { +void ShaderGraph::setPragma(const string &key, const string &value) { m_pragmas[key] = value; } -void ShaderNodeGraph::onNodeUpdated() { +void ShaderGraph::onNodeUpdated() { GraphNode *node = dynamic_cast(sender()); if(node) { markDirty(node); @@ -835,19 +843,19 @@ void ShaderNodeGraph::onNodeUpdated() { emit graphUpdated(); } -void ShaderNodeGraph::setPreviewVisible(GraphNode *node, bool visible) { +void ShaderGraph::setPreviewVisible(GraphNode *node, bool visible) { auto it = m_previews.find(node); if(it != m_previews.end()) { it->second.isVisible = visible; } } -void ShaderNodeGraph::updatePreviews(CommandBuffer &buffer) { +void ShaderGraph::updatePreviews(CommandBuffer &buffer) { for(auto &it : m_previews) { if(it.second.isVisible) { if(it.second.isDirty) { if(buildGraph(it.first)) { - VariantMap data = ShaderNodeGraph::data(true, &m_previewSettings); + VariantMap data = ShaderGraph::data(true, &m_previewSettings); ShaderBuilder::compileData(data); it.second.material->loadUserData(data); @@ -860,12 +868,12 @@ void ShaderNodeGraph::updatePreviews(CommandBuffer &buffer) { } buffer.setRenderTarget(it.second.target); buffer.clearRenderTarget(true, Vector4(0, 0, 0, 1)); - buffer.drawMesh(Matrix4(), PipelineContext::defaultPlane(), 0, CommandBuffer::TRANSLUCENT, *it.second.instance); + buffer.drawMesh(PipelineContext::defaultPlane(), 0, CommandBuffer::TRANSLUCENT, *it.second.instance); } } } -void ShaderNodeGraph::markDirty(GraphNode *node) { +void ShaderGraph::markDirty(GraphNode *node) { auto it = m_previews.find(node); if(it != m_previews.end()) { it->second.isDirty = true; @@ -878,7 +886,7 @@ void ShaderNodeGraph::markDirty(GraphNode *node) { } } -Texture *ShaderNodeGraph::preview(GraphNode *node) { +Texture *ShaderGraph::preview(GraphNode *node) { auto it = m_previews.find(node); if(it != m_previews.end()) { return it->second.texture; diff --git a/modules/editor/shadertools/converter/shadernodegraph.h b/modules/editor/shadertools/converter/shadergraph.h similarity index 93% rename from modules/editor/shadertools/converter/shadernodegraph.h rename to modules/editor/shadertools/converter/shadergraph.h index 532c533fc..b74bb3003 100644 --- a/modules/editor/shadertools/converter/shadernodegraph.h +++ b/modules/editor/shadertools/converter/shadergraph.h @@ -1,5 +1,5 @@ -#ifndef SHADERNODEGRAPH_H -#define SHADERNODEGRAPH_H +#ifndef SHADERGRAPH_H +#define SHADERGRAPH_H #include @@ -17,7 +17,7 @@ enum OldBlendType { Translucent }; -class ShaderNodeGraph : public AbstractNodeGraph { +class ShaderGraph : public AbstractNodeGraph { Q_OBJECT enum Stage { @@ -26,8 +26,8 @@ class ShaderNodeGraph : public AbstractNodeGraph { }; public: - ShaderNodeGraph(); - ~ShaderNodeGraph() Q_DECL_OVERRIDE; + ShaderGraph(); + ~ShaderGraph() Q_DECL_OVERRIDE; VariantMap data(bool editor = false, ShaderRootNode *root = nullptr); @@ -133,4 +133,4 @@ private slots: }; -#endif // SHADERNODEGRAPH_H +#endif // SHADERGRAPH_H diff --git a/modules/editor/shadertools/editor/materialedit.cpp b/modules/editor/shadertools/editor/materialedit.cpp index c72f45fbd..5bd4f64f2 100644 --- a/modules/editor/shadertools/editor/materialedit.cpp +++ b/modules/editor/shadertools/editor/materialedit.cpp @@ -34,7 +34,7 @@ namespace { class PreviewRender : public PipelineTask { public: - PreviewRender(ShaderNodeGraph *graph) : + PreviewRender(ShaderGraph *graph) : m_graph(graph) { } @@ -48,7 +48,7 @@ class PreviewRender : public PipelineTask { } private: - ShaderNodeGraph *m_graph; + ShaderGraph *m_graph; }; @@ -57,7 +57,7 @@ MaterialEdit::MaterialEdit() : m_mesh(nullptr), m_light(nullptr), m_material(nullptr), - m_graph(new ShaderNodeGraph), + m_graph(new ShaderGraph), m_builder(new ShaderBuilder()), m_controller(new CameraController), m_lastCommand(nullptr) { @@ -82,7 +82,7 @@ MaterialEdit::MaterialEdit() : on_actionSphere_triggered(); - connect(m_graph, &ShaderNodeGraph::graphUpdated, this, &MaterialEdit::onGraphUpdated); + connect(m_graph, &ShaderGraph::graphUpdated, this, &MaterialEdit::onGraphUpdated); connect(ui->schemeWidget, &GraphView::itemsSelected, this, &MaterialEdit::itemsSelected); ui->schemeWidget->setWorld(Engine::objectCreate("World")); diff --git a/modules/editor/shadertools/editor/materialedit.h b/modules/editor/shadertools/editor/materialedit.h index b5f81bc9f..95740e321 100644 --- a/modules/editor/shadertools/editor/materialedit.h +++ b/modules/editor/shadertools/editor/materialedit.h @@ -8,7 +8,7 @@ #include "shadercodedialog.h" class ShaderBuilder; -class ShaderNodeGraph; +class ShaderGraph; class CameraController; class UndoCommand; @@ -57,7 +57,7 @@ private slots: Material *m_material; - ShaderNodeGraph *m_graph; + ShaderGraph *m_graph; ShaderBuilder *m_builder; CameraController *m_controller; diff --git a/modules/editor/shadertools/shaders/Billboard.vert b/modules/editor/shadertools/shaders/Billboard.vert index 34620176f..92bb67eab 100644 --- a/modules/editor/shadertools/shaders/Billboard.vert +++ b/modules/editor/shadertools/shaders/Billboard.vert @@ -8,26 +8,10 @@ layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; layout(location = 2) in vec4 color; -#ifdef USE_TBN - layout(location = 3) in vec3 normal; - layout(location = 4) in vec3 tangent; -#endif - -layout(location = 7) in vec4 particlePosRot; -layout(location = 8) in vec4 particleSizeDist; -layout(location = 9) in vec4 particleRes1; -layout(location = 10) in vec4 particleRes2; - layout(location = 0) out vec4 _vertex; layout(location = 1) out vec2 _uv0; layout(location = 2) out vec4 _color; -#ifdef USE_TBN - layout(location = 3) out vec3 _n; - layout(location = 4) out vec3 _t; - layout(location = 5) out vec3 _b; -#endif - layout(location = 6) out vec3 _view; layout(location = 7) out int _instanceOffset; layout(location = 8) out mat4 _modelView; @@ -39,7 +23,7 @@ void main(void) { #pragma instance - _modelView = g.view * modelMatrix; + _modelView = g.view; vec3 camera = vec3(g.view[0].w, g.view[1].w, @@ -49,28 +33,26 @@ void main(void) { #pragma vertex - float angle = particlePosRot.w; // rotation + vec4 posRot = instance.data[_instanceOffset]; + vec4 sizeDist = instance.data[_instanceOffset + 1]; + + float angle = posRot.w; float x = cos(angle) * vertex.x + sin(angle) * vertex.y; float y = sin(angle) * vertex.x - cos(angle) * vertex.y; vec3 target = g.cameraTarget.xyz; - if(g.cameraProjection[2].w < 0.0) { - target = particlePosRot.xyz; + if(g.cameraProjection[2].w < 0.0f) { + target = posRot.xyz; } + vec3 normal = normalize(g.cameraPosition.xyz - target); - vec3 right = normalize(cross(vec3(0.0, 1.0, 0.0), normal)); + vec3 right = normalize(cross(vec3(0.0f, 1.0f, 0.0f), normal)); vec3 up = normalize(cross(normal, right)); - vec4 v = vec4((up * x + right * y) * particleSizeDist.xyz + particlePosRot.xyz + PositionOffset, 1.0); - - #ifdef USE_TBN - _t = tangent; - _n = normal; - _b = cross(_t, _n); - #endif + vec3 v = (up * x + right * y) * sizeDist.xyz + posRot.xyz + PositionOffset; - _vertex = g.projection * (_modelView * v); - _view = normalize((modelMatrix * v).xyz - camera); + _vertex = g.projection * (_modelView * vec4(v, 1.0f)); + _view = normalize(v - camera); _color = color; _uv0 = uv0; diff --git a/modules/editor/shadertools/shaders/Shader.frag b/modules/editor/shadertools/shaders/Shader.frag index 8969e7174..8ecd4abe0 100644 --- a/modules/editor/shadertools/shaders/Shader.frag +++ b/modules/editor/shadertools/shaders/Shader.frag @@ -54,7 +54,7 @@ void main(void) { vec3 emit = Emissive * _color.xyz; #ifdef VISIBILITY_BUFFER - gbuffer0 = vec4(0);//l.objectId; + gbuffer0 = vec4(objectId); return; #endif diff --git a/modules/editor/shadertools/shaders/Visibility.frag b/modules/editor/shadertools/shaders/Visibility.frag new file mode 100644 index 000000000..ecef42c05 --- /dev/null +++ b/modules/editor/shadertools/shaders/Visibility.frag @@ -0,0 +1,15 @@ +#version 450 core + +#pragma flags + +#include "ShaderLayout.h" + +layout(location = 7) flat in int _instanceOffset; + +layout(location = 0) out vec4 gbuffer0; + +void main(void) { +#pragma instance + + gbuffer0 = vec4(objectId); +} diff --git a/modules/editor/shadertools/shadertools.qrc b/modules/editor/shadertools/shadertools.qrc index 0aa741673..c40eb0bd8 100644 --- a/modules/editor/shadertools/shadertools.qrc +++ b/modules/editor/shadertools/shadertools.qrc @@ -31,5 +31,6 @@ shaders/Skinned.vert shaders/Shader.frag icons/material.png + shaders/Visibility.frag diff --git a/modules/renders/rendergl/includes/commandbuffergl.h b/modules/renders/rendergl/includes/commandbuffergl.h index 6296e1974..7e0bb38e2 100644 --- a/modules/renders/rendergl/includes/commandbuffergl.h +++ b/modules/renders/rendergl/includes/commandbuffergl.h @@ -24,9 +24,7 @@ class CommandBufferGL : public CommandBuffer { void dispatchCompute(ComputeInstance *shader, int32_t groupsX, int32_t groupsY, int32_t groupsZ) override; - void drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) override; - - void drawMeshInstanced(const Matrix4 *models, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance, uint32_t count) override; + void drawMesh(Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) override; void setRenderTarget(RenderTarget *target, uint32_t level = 0) override; diff --git a/modules/renders/rendergl/includes/resources/materialgl.h b/modules/renders/rendergl/includes/resources/materialgl.h index d5ca6fc8b..5fc010db9 100644 --- a/modules/renders/rendergl/includes/resources/materialgl.h +++ b/modules/renders/rendergl/includes/resources/materialgl.h @@ -16,7 +16,9 @@ class MaterialInstanceGL : public MaterialInstance { ~MaterialInstanceGL(); - bool bind(CommandBufferGL *buffer, uint32_t layer); + uint32_t drawsCount() const; + + bool bind(CommandBufferGL *buffer, uint32_t layer, uint32_t index); private: static void setBlendState(const Material::BlendState &state); @@ -70,8 +72,6 @@ class MaterialGL : public Material { Textures &textures() { return m_textures; } - uint32_t uniformSize() const; - protected: uint32_t buildShader(uint16_t type, const string &src = string()); diff --git a/modules/renders/rendergl/src/commandbuffergl.cpp b/modules/renders/rendergl/src/commandbuffergl.cpp index bc8fbc8de..707d1c7be 100644 --- a/modules/renders/rendergl/src/commandbuffergl.cpp +++ b/modules/renders/rendergl/src/commandbuffergl.cpp @@ -70,38 +70,32 @@ void CommandBufferGL::dispatchCompute(ComputeInstance *shader, int32_t groupsX, #endif } -void CommandBufferGL::drawMesh(const Matrix4 &model, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) { - PROFILE_FUNCTION(); - - drawMeshInstanced(&model, mesh, sub, layer, instance, 1); -} - -void CommandBufferGL::drawMeshInstanced(const Matrix4 *models, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &material, uint32_t count) { +void CommandBufferGL::drawMesh(Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) { PROFILE_FUNCTION(); if(mesh) { MeshGL *meshGL = static_cast(mesh); - material.setTransform(*models); - - MaterialInstanceGL &instanceGL = static_cast(material); - if(instanceGL.bind(this, layer)) { - meshGL->bindVao(this); - - if(meshGL->indices().empty()) { - int32_t glMode = (material.material()->wireframe()) ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; - uint32_t vert = meshGL->vertices().size(); - glDrawArraysInstanced(glMode, 0, vert, count); - PROFILER_STAT(POLYGONS, index - 2 * count); - } else { - int32_t index = meshGL->indexCount(sub); - int32_t glMode = (material.material()->wireframe()) ? GL_LINES : GL_TRIANGLES; - glDrawElementsInstanced(glMode, index, GL_UNSIGNED_INT, reinterpret_cast(meshGL->indexStart(sub) * sizeof(int32_t)), count); - PROFILER_STAT(POLYGONS, (index / 3) * count); + MaterialInstanceGL &instanceGL = static_cast(instance); + for(uint32_t index = 0; index < instanceGL.drawsCount(); index++) { + if(instanceGL.bind(this, layer, index)) { + meshGL->bindVao(this); + + if(meshGL->indices().empty()) { + int32_t glMode = (instance.material()->wireframe()) ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; + uint32_t vert = meshGL->vertices().size(); + glDrawArraysInstanced(glMode, 0, vert, instance.instanceCount()); + PROFILER_STAT(POLYGONS, index - 2 * count); + } else { + int32_t index = meshGL->indexCount(sub); + int32_t glMode = (instance.material()->wireframe()) ? GL_LINES : GL_TRIANGLES; + glDrawElementsInstanced(glMode, index, GL_UNSIGNED_INT, reinterpret_cast(meshGL->indexStart(sub) * sizeof(int32_t)), instance.instanceCount()); + PROFILER_STAT(POLYGONS, (index / 3) * count); + } + PROFILER_STAT(DRAWCALLS, 1); + + glBindVertexArray(0); } - PROFILER_STAT(DRAWCALLS, 1); - - glBindVertexArray(0); } } } diff --git a/modules/renders/rendergl/src/resources/materialgl.cpp b/modules/renders/rendergl/src/resources/materialgl.cpp index 891ac92f3..4d065ef82 100644 --- a/modules/renders/rendergl/src/resources/materialgl.cpp +++ b/modules/renders/rendergl/src/resources/materialgl.cpp @@ -9,7 +9,7 @@ #include -#define INSTANCE_SIZE 4096 +const uint32_t gMaxUBO = sizeof(Vector4) * 4096; namespace { const char *gVisibility("Visibility"); @@ -197,7 +197,7 @@ bool MaterialGL::checkShader(uint32_t shader) { buff.resize(value + 1); glGetShaderInfoLog(shader, value, nullptr, &buff[0]); - aError() << "[ Render::ShaderGL ]" << name() << "\n[ Shader Said ]" << buff; + aError() << "[ Render::MaterialGL ]" << name() << "\n[ Shader Said ]" << buff; } return false; } @@ -216,7 +216,7 @@ bool MaterialGL::checkProgram(uint32_t program) { buff.resize(value + 1); glGetProgramInfoLog(program, value, nullptr, &buff[0]); - aError() << "[ Render::ShaderGL ]" << name() << "\n[ Program Said ]" << buff; + aError() << "[ Render::MaterialGL ]" << name() << "\n[ Program Said ]" << buff; } return false; } @@ -242,10 +242,6 @@ MaterialInstance *MaterialGL::createInstance(SurfaceType type) { return result; } -uint32_t MaterialGL::uniformSize() const { - return m_uniformSize; -} - inline int32_t convertAction(int32_t action) { switch(action) { case Material::ActionType::Keep: return GL_KEEP; @@ -342,7 +338,11 @@ MaterialInstanceGL::~MaterialInstanceGL() { } } -bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer) { +uint32_t MaterialInstanceGL::drawsCount() const { + return (uint32_t)ceil((float)m_uniformBuffer.size() / (float)gMaxUBO); +} + +bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer, uint32_t index) { MaterialGL *material = static_cast(m_material); uint32_t program = material->bind(layer, surfaceType()); if(program) { @@ -351,13 +351,15 @@ bool MaterialInstanceGL::bind(CommandBufferGL *buffer, uint32_t layer) { if(m_instanceUbo == 0) { glGenBuffers(1, &m_instanceUbo); glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(Vector4) * INSTANCE_SIZE, nullptr, GL_DYNAMIC_DRAW); + glBufferData(GL_UNIFORM_BUFFER, gMaxUBO, nullptr, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } - if(m_uniformDirty) { + if(m_uniformDirty || index > 0) { + uint32_t offset = index * gMaxUBO; + glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); - glBufferSubData(GL_UNIFORM_BUFFER, 0, material->uniformSize(), m_uniformBuffer.data()); + glBufferSubData(GL_UNIFORM_BUFFER, 0, MIN(m_uniformBuffer.size() - offset, gMaxUBO), &m_uniformBuffer[offset]); glBindBuffer(GL_UNIFORM_BUFFER, 0); m_uniformDirty = false; } diff --git a/modules/uikit/src/components/frame.cpp b/modules/uikit/src/components/frame.cpp index abc3165d7..ef3e22d0e 100644 --- a/modules/uikit/src/components/frame.cpp +++ b/modules/uikit/src/components/frame.cpp @@ -69,7 +69,9 @@ void Frame::draw(CommandBuffer &buffer) { mat[12] -= verts[0].x; mat[13] -= verts[0].y; - buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, *m_material); + m_material->setTransform(mat, actor()->uuid()); + + buffer.drawMesh(m_mesh, 0, CommandBuffer::UI, *m_material); } } } diff --git a/modules/uikit/src/components/image.cpp b/modules/uikit/src/components/image.cpp index da516e89f..2a9915e5f 100644 --- a/modules/uikit/src/components/image.cpp +++ b/modules/uikit/src/components/image.cpp @@ -64,7 +64,10 @@ void Image::draw(CommandBuffer &buffer) { mat[12] -= verts[0].x; mat[13] -= verts[0].y; - buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, (m_customMaterial) ? *m_customMaterial : *m_material); + MaterialInstance &isntance = (m_customMaterial) ? *m_customMaterial : *m_material; + isntance.setTransform(mat, actor()->uuid()); + + buffer.drawMesh(m_mesh, 0, CommandBuffer::UI, isntance); } } } diff --git a/modules/uikit/src/components/label.cpp b/modules/uikit/src/components/label.cpp index 244b304b9..93b79b5b9 100644 --- a/modules/uikit/src/components/label.cpp +++ b/modules/uikit/src/components/label.cpp @@ -65,7 +65,9 @@ void Label::draw(CommandBuffer &buffer) { if(m_mesh && !m_text.empty()) { Transform *t = actor()->transform(); if(t) { - buffer.drawMesh(t->worldTransform(), m_mesh, 0, CommandBuffer::UI, *m_material); + m_material->setTransform(t->worldTransform(), actor()->uuid()); + + buffer.drawMesh(m_mesh, 0, CommandBuffer::UI, *m_material); } } } diff --git a/worldeditor/bin/editor/materials/checkerboard.shader b/worldeditor/bin/editor/materials/checkerboard.shader index 47e373d5c..994e7c9ad 100644 --- a/worldeditor/bin/editor/materials/checkerboard.shader +++ b/worldeditor/bin/editor/materials/checkerboard.shader @@ -3,6 +3,8 @@ - + - - - + + + - - - - - + + + + + - + - + - - + + - + diff --git a/worldeditor/bin/engine/materials/Downsample.shader b/worldeditor/bin/engine/materials/Downsample.shader index b264994d3..a00376b1d 100644 --- a/worldeditor/bin/engine/materials/Downsample.shader +++ b/worldeditor/bin/engine/materials/Downsample.shader @@ -1,18 +1,21 @@ - + - + - - - - + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + Date: Mon, 29 Apr 2024 09:27:19 +0300 Subject: [PATCH 6/6] update --- engine/src/components/particlerender.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/engine/src/components/particlerender.cpp b/engine/src/components/particlerender.cpp index 65807de03..40b5d7b27 100644 --- a/engine/src/components/particlerender.cpp +++ b/engine/src/components/particlerender.cpp @@ -1,6 +1,7 @@ #include "particlerender.h" #include +#include #include #include "actor.h"