diff --git a/engine/includes/commandbuffer.h b/engine/includes/commandbuffer.h index 2cfea408b..c1a827dcc 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,10 @@ 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 drawMeshInstanced(const Matrix4 *transform, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *material = nullptr); + virtual void drawMesh(Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance); 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 +95,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/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/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/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 14919ace5..82043ca31 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 { @@ -272,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); @@ -283,8 +284,12 @@ class ENGINE_EXPORT MaterialInstance { 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; @@ -301,9 +306,11 @@ class ENGINE_EXPORT MaterialInstance { map m_textureOverride; map m_paramOverride; + vector m_uniformBuffer; + Material *m_material; - uint8_t *m_uniformBuffer; + uint32_t m_instanceCount; uint16_t m_surfaceType; 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 f1fba4d8f..9f99a9f27 100644 --- a/engine/src/commandbuffer.cpp +++ b/engine/src/commandbuffer.cpp @@ -43,27 +43,13 @@ 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 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) { - 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(material); -} -/*! - 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. - 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) { - 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. @@ -97,24 +83,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/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/meshrender.cpp b/engine/src/components/meshrender.cpp index ccbe253f0..a474d41c3 100644 --- a/engine/src/components/meshrender.cpp +++ b/engine/src/components/meshrender.cpp @@ -34,16 +34,14 @@ 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); + 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 d0fc8e87c..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" @@ -26,6 +27,8 @@ namespace { */ ParticleRender::ParticleRender() : + m_ejectionTime(0.0f), + m_count(0.0f), m_effect(nullptr) { } @@ -56,77 +59,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())); + + 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); - std::sort(m_buffers[index].begin(), m_buffers[index].end(), [](const Matrix4 &left, const Matrix4 &right) { return left[7] > right[7]; }); + 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,15 +128,9 @@ 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++) { - if(m_visibleCount[index] > 0 && m_materials[index]) { - buffer.setMaterialId(m_materials[index]->material()->uuid()); - - ParticleEmitter *emitter = m_effect->emitter(index); - buffer.drawMeshInstanced(m_buffers[index].data(), m_visibleCount[index], emitter->mesh(), 0, layer, m_materials[index]); - } + MaterialInstance *instance = m_materials.front(); + if(instance && instance->instanceCount() > 0) { + buffer.drawMesh(m_effect->mesh(), 0, layer, *instance); } } } @@ -175,23 +161,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); } } @@ -236,30 +236,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 f5b362581..cd71ea3df 100644 --- a/engine/src/components/skinnedmeshrender.cpp +++ b/engine/src/components/skinnedmeshrender.cpp @@ -39,16 +39,14 @@ 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); + 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 77d5aaa7f..024f512b8 100644 --- a/engine/src/components/spriterender.cpp +++ b/engine/src/components/spriterender.cpp @@ -13,8 +13,10 @@ namespace { const char *gBaseMap = "BaseMap"; - const char *gOverride = "texture0"; - const char *gDefaultSprite = ".embedded/DefaultSprite.mtl"; + + const char *gColor = "mainColor"; + const char *gTexture = "mainTexture"; + const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; } static hash hash_str; @@ -66,13 +68,10 @@ 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()); + MaterialInstance &instance = *m_materials.front(); + instance.setTransform(t->worldTransform(), a->uuid()); - buffer.drawMesh(t->worldTransform(), - (m_customMesh) ? m_customMesh : m_mesh, - 0, layer, m_materials.front()); + buffer.drawMesh((m_customMesh) ? m_customMesh : m_mesh, 0, layer, instance); } } } @@ -108,7 +107,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()); } } } @@ -139,7 +138,7 @@ void SpriteRender::setTexture(Texture *texture) { } composeMesh(); - m_materials[0]->setTexture(gOverride, m_texture); + m_materials[0]->setTexture(gTexture, m_texture); } } /*! @@ -153,6 +152,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. @@ -239,8 +242,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); } } /*! @@ -371,6 +386,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]); @@ -385,6 +401,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); @@ -412,7 +429,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; @@ -467,14 +484,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..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 = "texture0"; + 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,11 +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.setObjectId(a->uuid()); - buffer.setMaterialId(material()->uuid()); - buffer.setColor(m_color); + MaterialInstance &instance = *m_materials.front(); + instance.setTransform(t->worldTransform(), a->uuid()); - buffer.drawMesh(t->worldTransform(), m_mesh, 0, layer, m_materials.front()); + buffer.drawMesh(m_mesh, 0, layer, instance); } } } @@ -99,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); @@ -112,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); + } } } /*! @@ -140,6 +144,9 @@ Vector4 TextRender::color() const { */ void TextRender::setColor(const Vector4 color) { m_color = color; + for(auto it : m_materials) { + it->setVector4(gColor, &m_color); + } } /*! Returns true if word wrap enabled; otherwise returns false. @@ -250,6 +257,7 @@ AABBox TextRender::localBound() const { if(m_mesh) { return m_mesh->bound(); } + return Renderable::localBound(); } /*! @@ -446,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 baccccac6..a15102639 100644 --- a/engine/src/components/tilemaprender.cpp +++ b/engine/src/components/tilemaprender.cpp @@ -15,7 +15,9 @@ namespace { const char *gTileMap = "TileMap"; const char *gMaterial = "Material"; - const char *gOverride = "texture0"; + const char *gColor = "mainColor"; + const char *gTexture = "mainTexture"; + const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; } /*! @@ -46,11 +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.setObjectId(a->uuid()); - buffer.setColor(Vector4(1.0f)); + MaterialInstance &instance = *m_materials.front(); + instance.setTransform(t->worldTransform(), a->uuid()); - buffer.setMaterialId(material()->uuid()); - buffer.drawMesh(t->worldTransform(), m_tileMap->tileMesh(), 0, layer, m_materials.front()); + buffer.drawMesh(m_tileMap->tileMesh(), 0, layer, instance); } } } @@ -85,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); } } } @@ -106,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); } } } @@ -128,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); { @@ -167,7 +183,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..1c6ac8d8b 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); @@ -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..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(); } @@ -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 { @@ -266,18 +269,18 @@ 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); + 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(m_plane, 0, CommandBuffer::TRANSLUCENT, *m_grid); buffer->endDebugMarker(); } @@ -345,8 +348,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); @@ -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 3d50c8fcb..93f8d371a 100644 --- a/engine/src/gizmos.cpp +++ b/engine/src/gizmos.cpp @@ -8,8 +8,6 @@ #include "commandbuffer.h" -#define OVERRIDE "texture0" - Mesh *Gizmos::s_wire = nullptr; Mesh *Gizmos::s_solid = nullptr; @@ -53,7 +51,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) { @@ -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 fe2e51d1e..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 db72c3453..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 26df476f6..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 25e5e9485..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 8a06d6a12..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 7a36bdbdb..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 e8d5856ec..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,18 +26,16 @@ namespace { MaterialInstance::MaterialInstance(Material *material) : m_material(material), - m_uniformBuffer(nullptr), + m_instanceCount(1), 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. */ @@ -52,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. @@ -185,16 +202,36 @@ 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. */ 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; } } @@ -205,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. */ @@ -389,11 +435,10 @@ void Material::loadUserData(const VariantMap &data) { } } { - m_uniformSize = 0; + size_t offset = sizeof(Matrix4); m_uniforms.clear(); auto it = data.find(gUniforms); if(it != data.end()) { - size_t offset = 0; VariantList uniforms = (*it).second.toList(); m_uniforms.resize(uniforms.size()); int i = 0; @@ -412,8 +457,8 @@ void Material::loadUserData(const VariantMap &data) { i++; } - m_uniformSize = offset; } + m_uniformSize = offset; } { m_attributes.clear(); @@ -552,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 924a090ba..501e1bfd1 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); } } @@ -43,13 +36,15 @@ 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; Vector2Vector uvs; + Vector4Vector colors; IndexVector indices; Vector3 pos = GraphController::worldPosition(); @@ -65,14 +60,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()) { @@ -82,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); } } @@ -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/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/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 6d01ca881..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"); @@ -129,6 +136,111 @@ ShaderBuilderSettings::Rhi ShaderBuilder::currentRhi() { return rhi; } +void ShaderBuilder::buildInstanceData(const VariantMap &user, PragmaMap &pragmas) { + string result; + + string modelMatrix = + " 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; + + 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", ""); @@ -162,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()) { @@ -173,18 +285,50 @@ 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()) { 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; @@ -216,12 +360,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); } @@ -231,42 +370,13 @@ AssetConverter::ReturnCode ShaderBuilder::convertFile(AssetConverterSettings *se data[SKINNED] = compile(rhi, it->second.toString(), inputs, EShLangVertex); } - it = data.find(FULLSCREEN); + it = data.find(GEOMETRY); if(it != data.end()) { - data[FULLSCREEN] = compile(rhi, it->second.toString(), inputs, EShLangVertex); + 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; @@ -288,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(); @@ -299,6 +409,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 +428,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,20 +445,23 @@ bool ShaderBuilder::parseShaderFormat(const QString &path, VariantMap &user, boo } string define; - const PragmaMap pragmas; + 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(materialType == Material::PostProcess) { - define += "\n#define TYPE_FULLSCREEN\n"; + if(currentRhi() == ShaderBuilderSettings::Rhi::Vulkan) { + define += "\n#define VULKAN"; } - if(currentRhi() == ShaderBuilderSettings::Rhi::Vulkan) { - define += "\n#define VULKAN\n"; + define += "\n#define USE_GBUFFER"; + + if(lightingModel == Material::Lit) { + define += "\n#define USE_TBN"; } string str; @@ -358,16 +472,35 @@ 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); } else { - user[STATIC] = loadIncludes("Default.vert", define, pragmas); + string file = "Static.vert"; + if(materialType == Material::PostProcess) { + 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]; if(!str.empty()) { - user[STATIC] = loadShader(GEOMETRY, define, pragmas); + user[GEOMETRY] = loadShader(str, define, pragmas); } } } @@ -376,6 +509,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 +573,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 +835,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 +852,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 319632a11..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" @@ -11,11 +11,8 @@ #define VISIBILITY "Visibility" #define STATIC "Static" -#define STATICINST "StaticInst" #define SKINNED "Skinned" -#define SKINNEDINST "SkinnedInst" #define PARTICLE "Particle" -#define FULLSCREEN "Fullscreen" #define GEOMETRY "Geometry" @@ -60,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; @@ -75,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); @@ -102,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; @@ -112,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 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); - 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/shadergraph.cpp similarity index 86% rename from modules/editor/shadertools/converter/shadernodegraph.cpp rename to modules/editor/shadertools/converter/shadergraph.cpp index 815f9cf7f..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) const { +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) const { 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; @@ -612,77 +619,53 @@ 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; + if(root != m_rootNode) { + define += "\n#define USE_GBUFFER"; + } + + if((root == m_rootNode) && 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 + "\n#define VISIBILITY_BUFFER", 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 != m_rootNode) || 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) { - { - string localDefine = define + "\n#define INSTANCING"; - Variant data = ShaderBuilder::loadIncludes("Static.vert", localDefine, m_pragmas); - if(data.isValid()) { - user[STATICINST] = data; - } - } - { + if(root->useWithSkinned()) { Variant data = ShaderBuilder::loadIncludes("Skinned.vert", define, m_pragmas); if(data.isValid()) { user[SKINNED] = data; @@ -695,7 +678,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; @@ -707,7 +690,7 @@ VariantMap ShaderNodeGraph::data(bool editor, ShaderRootNode *root) const { 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 }); @@ -718,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; @@ -729,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) { @@ -753,7 +736,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 +749,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 +762,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) { @@ -788,7 +770,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); @@ -836,25 +817,25 @@ 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)); } } } 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); @@ -862,34 +843,37 @@ 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)) { - it.second.material->loadUserData(data(true, &m_previewSettings)); + VariantMap data = ShaderGraph::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(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; @@ -902,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 92% rename from modules/editor/shadertools/converter/shadernodegraph.h rename to modules/editor/shadertools/converter/shadergraph.h index 8fb41f49b..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,10 +26,10 @@ class ShaderNodeGraph : public AbstractNodeGraph { }; public: - ShaderNodeGraph(); - ~ShaderNodeGraph() Q_DECL_OVERRIDE; + ShaderGraph(); + ~ShaderGraph() 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); @@ -133,4 +133,4 @@ private slots: }; -#endif // SHADERNODEGRAPH_H +#endif // SHADERGRAPH_H 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/editor/materialedit.cpp b/modules/editor/shadertools/editor/materialedit.cpp index 668d03614..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")); @@ -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/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 1302cad0d..92bb67eab 100644 --- a/modules/editor/shadertools/shaders/Billboard.vert +++ b/modules/editor/shadertools/shaders/Billboard.vert @@ -7,62 +7,52 @@ layout(location = 0) in vec3 vertex; layout(location = 1) in vec2 uv0; layout(location = 2) in vec4 color; -#ifdef MODEL_LIT - 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 MODEL_LIT - 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) { - mat4 model = l.model; +#pragma offset + +#pragma instance - _modelView = g.view * model; + _modelView = g.view; vec3 camera = vec3(g.view[0].w, g.view[1].w, g.view[2].w); + vec3 PositionOffset = vec3(0.0f); + #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 MODEL_LIT - _t = tangent; - _n = normal; - _b = cross(_t, _n); - #endif - _vertex = g.projection * (_modelView * v); - _view = normalize((model * v).xyz - camera); + vec3 v = (up * x + right * y) * sizeDist.xyz + posRot.xyz + PositionOffset; + + _vertex = g.projection * (_modelView * vec4(v, 1.0f)); + _view = normalize(v - camera); _color = color; _uv0 = uv0; 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..8ecd4abe0 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,30 +34,36 @@ layout(location = 3) out vec4 gbuffer3; #pragma functions void main(void) { +#pragma instance + + 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(objectId); 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 * l.color.xyz; + 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); @@ -68,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 04a3d5220..4a332a085 100644 --- a/modules/editor/shadertools/shaders/ShaderLayout.h +++ b/modules/editor/shadertools/shaders/ShaderLayout.h @@ -22,14 +22,8 @@ layout(set = 1, binding = GLOBAL) uniform Global { float padding[13]; } g; -layout(binding = LOCAL) uniform Local { - mat4 model; - - vec4 color; - - vec4 objectId; - - vec4 materialId; -} l; - -layout(binding = LOCAL + 1) uniform sampler2D radianceMap; +#ifndef NO_INSTANCE +layout(std140, set = 1, binding = LOCAL) uniform InstanceData { + vec4 data[4096]; +} instance; +#endif diff --git a/modules/editor/shadertools/shaders/Skinned.vert b/modules/editor/shadertools/shaders/Skinned.vert index 2f23ea39d..8a34b4736 100644 --- a/modules/editor/shadertools/shaders/Skinned.vert +++ b/modules/editor/shadertools/shaders/Skinned.vert @@ -4,10 +4,13 @@ #include "ShaderLayout.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 @@ -15,40 +18,35 @@ 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; -#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(binding = LOCAL + 2) uniform sampler2D skinMatrices; +layout(location = 7) out int _instanceOffset; +layout(location = 8) out mat4 _modelView; #pragma functions void main(void) { -#ifdef INSTANCING - mat4 model = instanceMatrix; -#else - mat4 model = l.model; -#endif - _modelView = g.view * model; +#pragma offset + +#pragma instance + + _modelView = g.view * modelMatrix; 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; @@ -70,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); @@ -78,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 diff --git a/modules/editor/shadertools/shaders/Static.vert b/modules/editor/shadertools/shaders/Static.vert index 37f04bca8..ef955056b 100644 --- a/modules/editor/shadertools/shaders/Static.vert +++ b/modules/editor/shadertools/shaders/Static.vert @@ -7,53 +7,52 @@ 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 -#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; -#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) { - #ifdef INSTANCING - mat4 model = instanceMatrix; - #else - mat4 model = l.model; - #endif - _modelView = g.view * model; +#pragma offset + +#pragma instance + + _modelView = g.view * modelMatrix; 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 - mat3 rot = mat3(model); + #ifdef USE_TBN + mat3 rot = mat3(modelMatrix); _t = normalize(rot * tangent); _n = normalize(rot * normal); _b = cross(_t, _n); #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; _uv0 = uv0; 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 a8d73670e..c40eb0bd8 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/Default.vert templates/Material.mtl shaders/functions/hsvToRgb.mtlf shaders/functions/gammaToLinear.mtlf @@ -32,5 +31,6 @@ shaders/Skinned.vert shaders/Shader.frag icons/material.png + shaders/Visibility.frag 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 829e80b2a..7e0bb38e2 100644 --- a/modules/renders/rendergl/includes/commandbuffergl.h +++ b/modules/renders/rendergl/includes/commandbuffergl.h @@ -12,25 +12,19 @@ #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; 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 drawMeshInstanced(const Matrix4 *models, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer = CommandBuffer::DEFAULT, MaterialInstance *material = nullptr) override; + void drawMesh(Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) override; void setRenderTarget(RenderTarget *target, uint32_t level = 0) override; @@ -51,7 +45,7 @@ class CommandBufferGL : public CommandBuffer { protected: uint32_t m_globalUbo; - uint32_t m_localUbo; + }; diff --git a/modules/renders/rendergl/includes/resources/materialgl.h b/modules/renders/rendergl/includes/resources/materialgl.h index 60d0ae1c9..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); @@ -28,14 +30,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 +49,8 @@ class MaterialGL : public Material { enum ShaderType { VertexStatic = 1, - VertexStaticInst, VertexSkinned, - VertexSkinnedInst, VertexParticle, - VertexFullscreen, VertexLast, FragmentDefault, @@ -73,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/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..707d1c7be 100644 --- a/modules/renders/rendergl/src/commandbuffergl.cpp +++ b/modules/renders/rendergl/src/commandbuffergl.cpp @@ -13,14 +13,9 @@ #include CommandBufferGL::CommandBufferGL() : - m_globalUbo(0), - m_localUbo(0) { - PROFILE_FUNCTION(); - -} - -CommandBufferGL::~CommandBufferGL() { + m_globalUbo(0) { + PROFILE_FUNCTION(); } void CommandBufferGL::begin() { @@ -42,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_localUbo == 0) { - glGenBuffers(1, &m_localUbo); - glBindBuffer(GL_UNIFORM_BUFFER, m_localUbo); - glBufferData(GL_UNIFORM_BUFFER, sizeof(Local), nullptr, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); - - glBindBufferBase(GL_UNIFORM_BUFFER, LOCAL_BIND, m_localUbo); - } } void CommandBufferGL::clearRenderTarget(bool clearColor, const Vector4 &color, bool clearDepth, float depth) { @@ -84,74 +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 *material) { - 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); - } - } -} - -void CommandBufferGL::drawMeshInstanced(const Matrix4 *models, uint32_t count, Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance *material) { +void CommandBufferGL::drawMesh(Mesh *mesh, uint32_t sub, uint32_t layer, MaterialInstance &instance) { PROFILE_FUNCTION(); - if(mesh && material) { - MeshGL *m = static_cast(mesh); - - m_local.model.identity(); - - 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); - - if(m->indices().empty()) { - int32_t glMode = (material->material()->wireframe()) ? GL_LINE_STRIP : GL_TRIANGLE_STRIP; - uint32_t vert = m->vertices().size(); - glDrawArraysInstanced(glMode, 0, vert, count); - PROFILER_STAT(POLYGONS, index - 2 * count); - } else { - int32_t index = m->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); - PROFILER_STAT(POLYGONS, (index / 3) * count); + if(mesh) { + MeshGL *meshGL = static_cast(mesh); + + 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 70ef03cfb..4d065ef82 100644 --- a/modules/renders/rendergl/src/resources/materialgl.cpp +++ b/modules/renders/rendergl/src/resources/materialgl.cpp @@ -9,15 +9,15 @@ #include +const uint32_t gMaxUBO = sizeof(Vector4) * 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} }; @@ -199,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; } @@ -218,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; } @@ -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; } @@ -246,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; @@ -336,6 +328,7 @@ MaterialInstanceGL::MaterialInstanceGL(Material *material) : m_stencilState.passOperationBack = convertAction(m_stencilState.passOperationBack); m_stencilState.passOperationFront = convertAction(m_stencilState.passOperationFront); + } MaterialInstanceGL::~MaterialInstanceGL() { @@ -345,31 +338,34 @@ 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) { 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_instanceUbo == 0) { + glGenBuffers(1, &m_instanceUbo); + glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); + glBufferData(GL_UNIFORM_BUFFER, gMaxUBO, 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_uniformDirty || index > 0) { + uint32_t offset = index * gMaxUBO; - glBindBufferBase(GL_UNIFORM_BUFFER, UNIFORM_BIND, m_instanceUbo); + glBindBuffer(GL_UNIFORM_BUFFER, m_instanceUbo); + glBufferSubData(GL_UNIFORM_BUFFER, 0, MIN(m_uniformBuffer.size() - offset, gMaxUBO), &m_uniformBuffer[offset]); + 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/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; -} diff --git a/modules/uikit/src/components/frame.cpp b/modules/uikit/src/components/frame.cpp index caa31b37c..ef3e22d0e 100644 --- a/modules/uikit/src/components/frame.cpp +++ b/modules/uikit/src/components/frame.cpp @@ -69,10 +69,9 @@ 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()); + m_material->setTransform(mat, actor()->uuid()); - buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, m_material); + 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 9f886ef0f..2a9915e5f 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 = "mainColor"; + const char *gDefaultSprite = ".embedded/DefaultSprite.shader"; }; static hash hash_str; @@ -64,10 +64,10 @@ 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()); + MaterialInstance &isntance = (m_customMaterial) ? *m_customMaterial : *m_material; + isntance.setTransform(mat, actor()->uuid()); - buffer.drawMesh(mat, m_mesh, 0, CommandBuffer::UI, (m_customMaterial) ? m_customMaterial : m_material); + 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 b3623ec6b..93b79b5b9 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,9 @@ 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); + m_material->setTransform(t->worldTransform(), actor()->uuid()); - buffer.setMaterialId(m_material->material()->uuid()); - buffer.drawMesh(t->worldTransform(), m_mesh, 0, CommandBuffer::UI, m_material); + buffer.drawMesh(m_mesh, 0, CommandBuffer::UI, *m_material); } } } @@ -143,7 +143,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 +174,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/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/editor/materials/gizmo.shader b/worldeditor/bin/editor/materials/gizmo.shader index d895e6cf6..4629ffd9c 100644 --- a/worldeditor/bin/editor/materials/gizmo.shader +++ b/worldeditor/bin/editor/materials/gizmo.shader @@ -5,6 +5,8 @@ + @@ -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(l.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(l.color.xyz, fog); + rgb = vec4(_color.xyz * mainColor.xyz, fog); } else { - rgb = vec4(l.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/editor/materials/outline.shader b/worldeditor/bin/editor/materials/outline.shader index af88e929a..630afdb85 100644 --- a/worldeditor/bin/editor/materials/outline.shader +++ b/worldeditor/bin/editor/materials/outline.shader @@ -2,20 +2,23 @@ - + - - - + + + - - - - - + + + + + - + - + - - + + + - + diff --git a/worldeditor/bin/engine/materials/DefaultMesh.mtl b/worldeditor/bin/engine/materials/DefaultMesh.mtl deleted file mode 100644 index 07d29c14f..000000000 --- a/worldeditor/bin/engine/materials/DefaultMesh.mtl +++ /dev/null @@ -1,20 +0,0 @@ - - - - - 0.8999999761581421 - - - - - - - - - - - - - - - diff --git a/worldeditor/bin/engine/materials/DefaultMesh.shader b/worldeditor/bin/engine/materials/DefaultMesh.shader new file mode 100644 index 000000000..9afc47003 --- /dev/null +++ b/worldeditor/bin/engine/materials/DefaultMesh.shader @@ -0,0 +1,46 @@ + + + + + + + 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.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..8fafe56c4 --- /dev/null +++ b/worldeditor/bin/engine/materials/DefaultSprite.shader @@ -0,0 +1,36 @@ + + + + + + + + + + + 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 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/IblReflections.shader b/worldeditor/bin/engine/materials/IblReflections.shader index 30a9369b2..01d273ab0 100644 --- a/worldeditor/bin/engine/materials/IblReflections.shader +++ b/worldeditor/bin/engine/materials/IblReflections.shader @@ -1,19 +1,21 @@ - - - - + + + + - - - - - - - - - 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 4d93ba490..4b65fe692 100644 --- a/worldeditor/bin/engine/materials/Link.shader +++ b/worldeditor/bin/engine/materials/Link.shader @@ -1,40 +1,18 @@ - - - - + diff --git a/worldeditor/bin/engine/materials/PointLight.shader b/worldeditor/bin/engine/materials/PointLight.shader index 97e4d16d9..830420f45 100644 --- a/worldeditor/bin/engine/materials/PointLight.shader +++ b/worldeditor/bin/engine/materials/PointLight.shader @@ -8,22 +8,25 @@ - - - - - + + + + + - - - - + + + + - - - - - + + + + +