diff --git a/core/2d/AtlasNode.cpp b/core/2d/AtlasNode.cpp index 7f0ed2b25a..6165055724 100644 --- a/core/2d/AtlasNode.cpp +++ b/core/2d/AtlasNode.cpp @@ -92,9 +92,9 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh return true; } -bool AtlasNode::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool AtlasNode::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/) { - if (Node::setProgramState(programState, needsRetain)) + if (Node::setProgramState(programState, ownPS)) { auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); pipelineDescriptor.programState = _programState; diff --git a/core/2d/AtlasNode.h b/core/2d/AtlasNode.h index 12bd3d1a86..ab40cff971 100644 --- a/core/2d/AtlasNode.h +++ b/core/2d/AtlasNode.h @@ -99,7 +99,7 @@ public: void setQuadsToDraw(ssize_t quadsToDraw); size_t getQuadsToDraw() const; - bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; + bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; AtlasNode() = default; virtual ~AtlasNode(); diff --git a/core/2d/DrawNode.cpp b/core/2d/DrawNode.cpp index 770618f3b0..c717adecc3 100644 --- a/core/2d/DrawNode.cpp +++ b/core/2d/DrawNode.cpp @@ -178,11 +178,11 @@ void DrawNode::updateShaderInternal(CustomCommand& cmd, void DrawNode::setVertexLayout(CustomCommand& cmd) { auto* programState = cmd.getPipelineDescriptor().programState; - programState->validateSharedVertexLayout(VertexLayoutHelper::setupDrawNode); + programState->validateSharedVertexLayout(backend::VertexLayoutType::DrawNode); } void DrawNode::freeShaderInternal(CustomCommand& cmd) -{ +{ auto& pipelinePS = cmd.getPipelineDescriptor().programState; AX_SAFE_RELEASE_NULL(pipelinePS); } diff --git a/core/2d/Grid.cpp b/core/2d/Grid.cpp index f6236c3f2a..db25297b87 100644 --- a/core/2d/Grid.cpp +++ b/core/2d/Grid.cpp @@ -117,17 +117,19 @@ bool GridBase::initWithSize(const Vec2& gridSize, Texture2D* texture, bool flipp uint32_t totalSize = (VERTEX_POSITION_SIZE + VERTEX_TEXCOORD_SIZE) * sizeof(float); const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); auto iter = attributeInfo.find("a_position"); + + auto layout = _programState->getMutableVertexLayout(); if (iter != attributeInfo.end()) { - _programState->setVertexAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false); + layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false); } iter = attributeInfo.find("a_texCoord"); if (iter != attributeInfo.end()) { - _programState->setVertexAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, texcoordOffset, + layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, texcoordOffset, false); } - _programState->setVertexStride(totalSize); + layout->setStride(totalSize); calculateVertexPoints(); updateBlendState(); diff --git a/core/2d/Label.cpp b/core/2d/Label.cpp index ca8ca1aecf..3ac897ffa3 100644 --- a/core/2d/Label.cpp +++ b/core/2d/Label.cpp @@ -676,12 +676,12 @@ static Texture2D* _getTexture(Label* label) void Label::setVertexLayout() { - _programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite); + _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite); } -bool Label::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool Label::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/) { - if (Node::setProgramState(programState, needsRetain)) + if (Node::setProgramState(programState, ownPS)) { updateUniformLocations(); for (auto&& batch : _batchCommands) @@ -743,8 +743,7 @@ void Label::updateShaderProgram() } } - auto* program = backend::Program::getBuiltinProgram(programType); - setProgramState(new backend::ProgramState(program), false); + this->setProgramStateByProgramId(programType); updateUniformLocations(); diff --git a/core/2d/Label.h b/core/2d/Label.h index 00f4aec9f5..bd29795aec 100644 --- a/core/2d/Label.h +++ b/core/2d/Label.h @@ -674,7 +674,7 @@ public: */ float getAdditionalKerning() const; - bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; + bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; FontAtlas* getFontAtlas() { return _fontAtlas; } diff --git a/core/2d/MotionStreak.cpp b/core/2d/MotionStreak.cpp index 2c0578dfa4..6d7b1bf35e 100644 --- a/core/2d/MotionStreak.cpp +++ b/core/2d/MotionStreak.cpp @@ -221,9 +221,9 @@ void MotionStreak::setTexture(Texture2D* texture) } } -bool MotionStreak::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool MotionStreak::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/) { - if (Node::setProgramState(programState, needsRetain)) + if (Node::setProgramState(programState, ownPS)) { AXASSERT(programState, "argument should not be nullptr"); auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); @@ -235,23 +235,24 @@ bool MotionStreak::setProgramState(backend::ProgramState* programState, bool nee // setup custom vertex layout for V2F_T2F_C4B const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); auto iter = attributeInfo.find("a_position"); + auto layout = _programState->getMutableVertexLayout(); if (iter != attributeInfo.end()) { - _programState->setVertexAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false); + layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false); } iter = attributeInfo.find("a_texCoord"); if (iter != attributeInfo.end()) { - _programState->setVertexAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, + layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, 2 * sizeof(float), false); } iter = attributeInfo.find("a_color"); if (iter != attributeInfo.end()) { - _programState->setVertexAttrib("a_color", iter->second.location, backend::VertexFormat::UBYTE4, + layout->setAttrib("a_color", iter->second.location, backend::VertexFormat::UBYTE4, 4 * sizeof(float), true); } - _programState->setVertexStride(4 * sizeof(float) + 4 * sizeof(uint8_t)); + layout->setStride(4 * sizeof(float) + 4 * sizeof(uint8_t)); updateProgramStateTexture(_texture); return true; diff --git a/core/2d/MotionStreak.h b/core/2d/MotionStreak.h index 958658fc32..98dc6ee94c 100644 --- a/core/2d/MotionStreak.h +++ b/core/2d/MotionStreak.h @@ -156,7 +156,7 @@ public: _startingPositionInitialized = bStartingPositionInitialized; } - bool setProgramState(backend::ProgramState* programState, bool needsRetain) override; + bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; MotionStreak(); virtual ~MotionStreak(); diff --git a/core/2d/Node.cpp b/core/2d/Node.cpp index 0bbb1e3cc5..1a9557c9c3 100644 --- a/core/2d/Node.cpp +++ b/core/2d/Node.cpp @@ -45,6 +45,7 @@ THE SOFTWARE. #include "2d/Component.h" #include "renderer/Material.h" #include "math/TransformUtils.h" +#include "renderer/backend/ProgramManager.h" #include "renderer/backend/ProgramStateRegistry.h" #if AX_NODE_RENDER_SUBPIXEL @@ -2228,22 +2229,33 @@ void Node::setProgramStateWithRegistry(uint32_t programType, Texture2D* texture) { auto samplerFlags = texture ? texture->getSamplerFlags() : 0; auto programState = backend::ProgramStateRegistry::getInstance()->newProgramState(programType, samplerFlags); - setProgramState(programState, false); + setProgramState(programState, true); } -bool Node::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool Node::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) { if (_programState != programState) { AX_SAFE_RELEASE(_programState); _programState = programState; - if (needsRetain) + if (!ownPS) AX_SAFE_RETAIN(_programState); return !!_programState; } return false; } +backend::ProgramState* Node::setProgramStateByProgramId(uint64_t programId) +{ + auto prog = ProgramManager::getInstance()->loadProgram(programId); + if (prog) + { + this->setProgramState(new ProgramState(prog), true); + return _programState; + } + return nullptr; +} + void Node::updateProgramStateTexture(Texture2D* texture) { if (texture == nullptr || texture->getBackendTexture() == nullptr || _programState == nullptr) diff --git a/core/2d/Node.h b/core/2d/Node.h index 794873e3b7..a8b5446968 100644 --- a/core/2d/Node.h +++ b/core/2d/Node.h @@ -1828,7 +1828,14 @@ public: * Sets ProgramState with retain * @param programState */ - virtual bool setProgramState(backend::ProgramState* programState, bool needsRetain = true); + virtual bool setProgramState(backend::ProgramState* programState, bool ownPS = false); + + /** + * Sets ProgramState by programId + * @param progId the program id or programType used to create programState + * @return ProgramState* (nullable) + */ + backend::ProgramState* setProgramStateByProgramId(uint64_t progId); backend::ProgramState* getProgramState() const; diff --git a/core/2d/ProgressTimer.cpp b/core/2d/ProgressTimer.cpp index e7e1fd2bb8..b8f91f1bb7 100644 --- a/core/2d/ProgressTimer.cpp +++ b/core/2d/ProgressTimer.cpp @@ -57,15 +57,16 @@ backend::ProgramState* initPipelineDescriptor(ax::CustomCommand& command, pipelieDescriptor.programState = programState; // set custom vertexLayout according to V2F_C4B_T2F structure - programState->setVertexAttrib("a_position", program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - programState->setVertexAttrib("a_texCoord", program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, - offsetof(V2F_C4B_T2F, texCoords), false); - programState->setVertexAttrib("a_color", program->getAttributeLocation(backend::Attribute::COLOR), + auto vertexLayout = programState->getMutableVertexLayout(); + vertexLayout->setAttrib("a_position", program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT2, 0, false); + vertexLayout->setAttrib("a_texCoord", program->getAttributeLocation(backend::Attribute::TEXCOORD), + backend::VertexFormat::FLOAT2, + offsetof(V2F_C4B_T2F, texCoords), false); + vertexLayout->setAttrib("a_color", program->getAttributeLocation(backend::Attribute::COLOR), backend::VertexFormat::UBYTE4, offsetof(V2F_C4B_T2F, colors), true); - programState->setVertexStride(sizeof(V2F_C4B_T2F)); + vertexLayout->setStride(sizeof(V2F_C4B_T2F)); if (ridal) { @@ -107,7 +108,7 @@ bool ProgressTimer::initWithSprite(Sprite* sp) // TODO: Use ProgramState Vector to Node AX_SAFE_RELEASE(_programState2); - setProgramState(initPipelineDescriptor(_customCommand, true, _locMVP1, _locTex1), false); + setProgramState(initPipelineDescriptor(_customCommand, true, _locMVP1, _locTex1), true); _programState2 = initPipelineDescriptor(_customCommand2, false, _locMVP2, _locTex2); return true; diff --git a/core/2d/RenderTexture.cpp b/core/2d/RenderTexture.cpp index 890255f3bd..c7464159a4 100644 --- a/core/2d/RenderTexture.cpp +++ b/core/2d/RenderTexture.cpp @@ -159,7 +159,7 @@ bool RenderTexture::initWithWidthAndHeight(int w, PixelFormat depthStencilFormat, bool sharedRenderTarget) { - AXASSERT(format == backend::PixelFormat::RGBA8 || format == PixelFormat::RGB8, "only RGB and RGBA formats are valid for a render texture"); + AXASSERT(format == backend::PixelFormat::RGBA8 || format == PixelFormat::RGB8 || format == PixelFormat::RGBA4, "only RGB and RGBA formats are valid for a render texture"); bool ret = false; do diff --git a/core/2d/Sprite.cpp b/core/2d/Sprite.cpp index 3bcff3b2b7..040f84b3a8 100644 --- a/core/2d/Sprite.cpp +++ b/core/2d/Sprite.cpp @@ -358,7 +358,7 @@ void Sprite::setTexture(std::string_view filename) void Sprite::setVertexLayout() { AXASSERT(_programState, "programState should not be nullptr"); - _programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite); + _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite); } void Sprite::setProgramState(uint32_t type) @@ -366,10 +366,10 @@ void Sprite::setProgramState(uint32_t type) setProgramStateWithRegistry(type, _texture); } -bool Sprite::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool Sprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) { AXASSERT(programState, "argument should not be nullptr"); - if (Node::setProgramState(programState, needsRetain)) + if (Node::setProgramState(programState, ownPS)) { auto& pipelineDescriptor = _trianglesCommand.getPipelineDescriptor(); pipelineDescriptor.programState = _programState; diff --git a/core/2d/Sprite.h b/core/2d/Sprite.h index 6cc54e789e..64153e5f9d 100644 --- a/core/2d/Sprite.h +++ b/core/2d/Sprite.h @@ -425,7 +425,7 @@ public: /** * Set or Attach new ProgramState */ - bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; + bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; /** * Sets the weak reference of the TextureAtlas when the sprite is rendered using via SpriteBatchNode. diff --git a/core/2d/SpriteBatchNode.cpp b/core/2d/SpriteBatchNode.cpp index 2447219a9c..39b046f565 100644 --- a/core/2d/SpriteBatchNode.cpp +++ b/core/2d/SpriteBatchNode.cpp @@ -124,13 +124,13 @@ void SpriteBatchNode::setUniformLocation() void SpriteBatchNode::setVertexLayout() { AXASSERT(_programState, "programState should not be nullptr"); - _programState->validateSharedVertexLayout(VertexLayoutHelper::setupSprite); + _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite); } -bool SpriteBatchNode::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool SpriteBatchNode::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) { AXASSERT(programState, "programState should not be nullptr"); - if (Node::setProgramState(programState, needsRetain)) + if (Node::setProgramState(programState, ownPS)) { auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); pipelineDescriptor.programState = _programState; diff --git a/core/2d/SpriteBatchNode.h b/core/2d/SpriteBatchNode.h index 359ce72120..44903b1e45 100644 --- a/core/2d/SpriteBatchNode.h +++ b/core/2d/SpriteBatchNode.h @@ -213,7 +213,7 @@ public: */ virtual std::string getDescription() const override; - bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; + bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; /** Inserts a quad at a certain index into the texture atlas. The Sprite won't be added into the children array. * This method should be called only when you are dealing with very big AtlasSprite and when most of the Sprite diff --git a/core/3d/MeshRenderer.cpp b/core/3d/MeshRenderer.cpp index c5cfaef906..e65e24e828 100644 --- a/core/3d/MeshRenderer.cpp +++ b/core/3d/MeshRenderer.cpp @@ -835,9 +835,9 @@ void MeshRenderer::draw(Renderer* renderer, const Mat4& transform, uint32_t flag } } -bool MeshRenderer::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool MeshRenderer::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) { - if (Node::setProgramState(programState, needsRetain)) + if (Node::setProgramState(programState, ownPS)) { for (auto&& state : _meshes) { diff --git a/core/3d/MeshRenderer.h b/core/3d/MeshRenderer.h index 24512da716..9a233d6a61 100644 --- a/core/3d/MeshRenderer.h +++ b/core/3d/MeshRenderer.h @@ -129,7 +129,7 @@ public: // overrides /** Sets ProgramState, attributes should be bound by the user */ - bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; + bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; /* * Get AABB diff --git a/core/3d/MotionStreak3D.cpp b/core/3d/MotionStreak3D.cpp index 063e58ce1a..fc81f23364 100644 --- a/core/3d/MotionStreak3D.cpp +++ b/core/3d/MotionStreak3D.cpp @@ -121,8 +121,7 @@ bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED; // shader state - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); - setProgramState(new backend::ProgramState(program), false); + this->setProgramStateByProgramId(ProgramType::POSITION_TEXTURE_COLOR); _customCommand.getPipelineDescriptor().programState = _programState; diff --git a/core/3d/Skybox.cpp b/core/3d/Skybox.cpp index 36c91ad26f..b9d320c747 100644 --- a/core/3d/Skybox.cpp +++ b/core/3d/Skybox.cpp @@ -64,8 +64,7 @@ bool Skybox::init() _customCommand.setAfterCallback(AX_CALLBACK_0(Skybox::onAfterDraw, this)); // create and set our custom shader - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::SKYBOX_3D); - setProgramState(new backend::ProgramState(program), false); + setProgramStateByProgramId(backend::ProgramType::SKYBOX_3D); auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); diff --git a/core/3d/Terrain.cpp b/core/3d/Terrain.cpp index 5a927a0190..114336048a 100644 --- a/core/3d/Terrain.cpp +++ b/core/3d/Terrain.cpp @@ -106,8 +106,7 @@ void ax::Terrain::setLightDir(const Vec3& lightDir) bool Terrain::initProperties() { - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::TERRAIN_3D); - setProgramState(new backend::ProgramState(program), false); + setProgramStateByProgramId(ProgramType::TERRAIN_3D); _stateBlock.depthWrite = true; _stateBlock.depthTest = true; diff --git a/core/3d/VertexAttribBinding.cpp b/core/3d/VertexAttribBinding.cpp index 9e215be348..d2cb576fe0 100644 --- a/core/3d/VertexAttribBinding.cpp +++ b/core/3d/VertexAttribBinding.cpp @@ -90,15 +90,17 @@ bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCom // Parse and set attributes parseAttributes(); int offset = 0; + auto vertexLayout = _programState->getMutableVertexLayout(); for (auto k = 0; k < attributeCount; k++) { auto meshattribute = meshVertexData->getMeshVertexAttrib(k); - setVertexAttribPointer(shaderinfos::getAttributeName(meshattribute.vertexAttrib), meshattribute.type, false, + setVertexAttribPointer(vertexLayout, shaderinfos::getAttributeName(meshattribute.vertexAttrib), + meshattribute.type, false, offset, 1 << k); offset += meshattribute.getAttribSizeBytes(); } - _programState->setVertexStride(offset); + vertexLayout->setStride(offset); AXASSERT(offset == meshVertexData->getSizePerVertex(), "vertex layout mismatch!"); @@ -133,7 +135,8 @@ const backend::AttributeBindInfo* VertexAttribBinding::getVertexAttribValue(std: return nullptr; } -void VertexAttribBinding::setVertexAttribPointer(std::string_view name, +void VertexAttribBinding::setVertexAttribPointer(VertexLayout* vertexLayout, + std::string_view name, backend::VertexFormat type, bool normalized, int offset, @@ -143,7 +146,7 @@ void VertexAttribBinding::setVertexAttribPointer(std::string_view name, if (v) { // AXLOG("axmol: set attribute '%s' location: %d, offset: %d", name.c_str(), v->location, offset); - _programState->setVertexAttrib(name, v->location, type, offset, normalized); + vertexLayout->setAttrib(name, v->location, type, offset, normalized); _vertexAttribsFlags |= flag; } else diff --git a/core/3d/VertexAttribBinding.h b/core/3d/VertexAttribBinding.h index 092fc2b186..9e4a99740c 100644 --- a/core/3d/VertexAttribBinding.h +++ b/core/3d/VertexAttribBinding.h @@ -107,7 +107,7 @@ private: VertexAttribBinding& operator=(const VertexAttribBinding&); bool init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand*); - void setVertexAttribPointer(std::string_view name, + void setVertexAttribPointer(VertexLayout* vertexLayout, std::string_view name, backend::VertexFormat type, bool normalized, int offset, diff --git a/core/platform/desktop/GLViewImpl-desktop.cpp b/core/platform/desktop/GLViewImpl-desktop.cpp index 5a67e2931b..c2206b5afc 100644 --- a/core/platform/desktop/GLViewImpl-desktop.cpp +++ b/core/platform/desktop/GLViewImpl-desktop.cpp @@ -566,9 +566,7 @@ bool GLViewImpl::initWithRect(std::string_view viewName, const ax::Rect& rect, f #endif #if defined(AX_USE_GL) - CHECK_GL_ERROR_DEBUG(); glfwSwapInterval(_glContextAttrs.vsync ? 1 : 0); - CHECK_GL_ERROR_DEBUG(); // check OpenGL version at first const GLubyte* glVersion = glGetString(GL_VERSION); diff --git a/core/renderer/CMakeLists.txt b/core/renderer/CMakeLists.txt index 9ce79c0809..0f7558de30 100644 --- a/core/renderer/CMakeLists.txt +++ b/core/renderer/CMakeLists.txt @@ -1,6 +1,5 @@ set(_AX_RENDERER_HEADER renderer/CallbackCommand.h - renderer/Colorizer.h renderer/CustomCommand.h renderer/GroupCommand.h renderer/Material.h @@ -63,7 +62,6 @@ set(_AX_RENDERER_SRC renderer/TextureCube.cpp renderer/TrianglesCommand.cpp renderer/Shaders.cpp - renderer/Colorizer.cpp renderer/backend/ProgramManager.cpp renderer/backend/ProgramStateRegistry.cpp diff --git a/core/renderer/Colorizer.cpp b/core/renderer/Colorizer.cpp deleted file mode 100644 index f2dd3a8692..0000000000 --- a/core/renderer/Colorizer.cpp +++ /dev/null @@ -1,865 +0,0 @@ -#include "Colorizer.h" -#include "math/Mat3.h" -#include "2d/Node.h" -#include "renderer/Shaders.h" -#include "renderer/backend/Device.h" - -NS_AX_BEGIN - -#define FLT_SQRT_2 1.4142135623730950488016887242097 -#define FLT_SQRT_3 1.7320508075688772935274463415059 -#define FLT_XRS (1 / FLT_SQRT_2) -#define FLT_XRC FLT_XRS -#define FLT_YRS (-1 / FLT_SQRT_3) -#define FLT_YRC (FLT_SQRT_2 / FLT_SQRT_3) -#define RLUM (0.3086) -#define GLUM (0.6094) -#define BLUM (0.0820) - -#define CLZ_PRINTMAT 0 - -typedef float _M3X3[3][3]; -typedef float _M4X4[4][4]; - -static Vec3 fastest_rgb2hsv(const Color3B& rgb) -{ - float r = rgb.r / 255.0f; - float g = rgb.g / 255.0f; - float b = rgb.b / 255.0f; - - float h, s, v; - - float K = 0.f; - - if (g < b) - { - std::swap(g, b); - K = -1.f; - } - - if (r < g) - { - std::swap(r, g); - K = -2.f / 6.f - K; - } - - float chroma = r - std::min(g, b); - h = fabs(K + (g - b) / (6.f * chroma + 1e-20f)); - s = chroma / (r + 1e-20f); - v = r; - - return Vec3(h, s, v); -} - -static Vec3 rgb2hsv(const Color3B& rgb) -{ - unsigned char dst_h, dst_s, dst_v; - - float r = rgb.r / 255.0f; - float g = rgb.g / 255.0f; - float b = rgb.b / 255.0f; - - float h, s, v; // h:0-360.0, s:0.0-1.0, v:0.0-1.0 - - float max = std::max({r, g, b}); - float min = std::min({r, g, b}); - - v = max; - - if (max == 0.0f) - { - s = 0; - h = 0; - } - else if (max - min == 0.0f) - { - s = 0; - h = 0; - } - else - { - s = (max - min) / max; - - if (max == r) - { - h = 60 * ((g - b) / (max - min)) + 0; - } - else if (max == g) - { - h = 60 * ((b - r) / (max - min)) + 120; - } - else - { - h = 60 * ((r - g) / (max - min)) + 240; - } - } - - if (h < 0) - h += 360.0f; - - dst_h = (unsigned char)(h / 2); // dst_h : 0-180 - dst_s = (unsigned char)(s /* * 255*/); // dst_s : 0-255 - dst_v = (unsigned char)(v /** 255*/); // dst_v : 0-255 - - return Vec3(dst_h / 180.f, dst_s, dst_v); -} - -static void hsv2rgb(const unsigned char& src_h, - const unsigned char& src_s, - const unsigned char& src_v, - unsigned char& dst_r, - unsigned char& dst_g, - unsigned char& dst_b) -{ - float h = src_h * 2.0f; // 0-360 - float s = src_s / 255.0f; // 0.0-1.0 - float v = src_v / 255.0f; // 0.0-1.0 - - float r, g, b; // 0.0-1.0 - - int hi = (int)(h / 60.0f) % 6; - float f = (h / 60.0f) - hi; - float p = v * (1.0f - s); - float q = v * (1.0f - s * f); - float t = v * (1.0f - s * (1.0f - f)); - - switch (hi) - { - case 0: - r = v, g = t, b = p; - break; - case 1: - r = q, g = v, b = p; - break; - case 2: - r = p, g = v, b = t; - break; - case 3: - r = p, g = q, b = v; - break; - case 4: - r = t, g = p, b = v; - break; - case 5: - r = v, g = p, b = q; - break; - } - - dst_r = (unsigned char)(r * 255); // dst_r : 0-255 - dst_g = (unsigned char)(g * 255); // dst_r : 0-255 - dst_b = (unsigned char)(b * 255); // dst_r : 0-255 -} - -#if CLZ_PRINTMAT -static void printmat3(float mat[3][3]) -{ - int x, y; - char svalue[256]; - int n = 0; - for (y = 0; y < 3; y++) - { - for (x = 0; x < 3; x++) - n += sprintf(svalue + n, "%f ", mat[y][x]); - n += sprintf(svalue + n, "\n"); - } - n += sprintf(svalue + n, "\n"); - - log("%s", svalue); -} - -static void printmat4(float mat[4][4]) -{ - int x, y; - char svalue[256]; - int n = 0; - for (y = 0; y < 4; y++) - { - for (x = 0; x < 4; x++) - n += sprintf(svalue + n, "%f ", mat[y][x]); - n += sprintf(svalue + n, "\n"); - } - n += sprintf(svalue + n, "\n"); - - log("%s", svalue); -} - -inline void printmat3(float (&mat)[9]) -{ - printmat3((_M3X3&)mat); -} - -inline void printmat4(float (&mat)[16]) -{ - printmat4((_M4X4&)mat); -} -#endif - -inline void createRotationX(Mat4* dst, float sv, float cv) -{ - dst->m[5] = cv; - dst->m[6] = sv; - dst->m[9] = -sv; - dst->m[10] = cv; -} - -inline void createRotationY(Mat4* dst, float sv, float cv) -{ - dst->m[0] = cv; - dst->m[2] = -sv; - dst->m[8] = sv; - dst->m[10] = cv; -} - -inline void createRotationZ(Mat4* dst, float sv, float cv) -{ - dst->m[0] = cv; - dst->m[1] = sv; - dst->m[4] = -sv; - dst->m[5] = cv; -} - -inline void rotateX(Mat4* dst, float sv, float cv) -{ - Mat4 temp; - createRotationX(&temp, sv, cv); - Mat4::multiply(temp, *dst, dst); -} - -inline void rotateY(Mat4* dst, float sv, float cv) -{ - Mat4 temp; - createRotationY(&temp, sv, cv); - Mat4::multiply(temp, *dst, dst); // dst->multiply(temp); pitfall: matrix1 * matrix2 != matrix2 * matrix1 -} - -inline void rotateZ(Mat4* dst, float sv, float cv) -{ - Mat4 temp; - createRotationZ(&temp, sv, cv); - Mat4::multiply(temp, *dst, dst); -} - -inline void rotateZ(Mat4* dst, float angle) -{ - Mat4 temp; - Mat4::createRotationZ(angle, &temp); - Mat4::multiply(temp, *dst, dst); -} - -/* - * matrixmult - - * multiply two matricies - */ -static void matrixmult(float a[4][4], float b[4][4], float c[4][4]) -{ - int x, y; - float temp[4][4]; - - for (y = 0; y < 4; y++) - for (x = 0; x < 4; x++) - { - temp[y][x] = b[y][0] * a[0][x] + b[y][1] * a[1][x] + b[y][2] * a[2][x] + b[y][3] * a[3][x]; - } - for (y = 0; y < 4; y++) - for (x = 0; x < 4; x++) - c[y][x] = temp[y][x]; -} - -/* - * identmat - - * make an identity matrix - */ -inline void identmat(float* matrix) -{ - *matrix++ = 1.0; /* row 1 */ - *matrix++ = 0.0; - *matrix++ = 0.0; - *matrix++ = 0.0; - *matrix++ = 0.0; /* row 2 */ - *matrix++ = 1.0; - *matrix++ = 0.0; - *matrix++ = 0.0; - *matrix++ = 0.0; /* row 3 */ - *matrix++ = 0.0; - *matrix++ = 1.0; - *matrix++ = 0.0; - *matrix++ = 0.0; /* row 4 */ - *matrix++ = 0.0; - *matrix++ = 0.0; - *matrix++ = 1.0; -} - -/* - * xformpnt - - * transform a 3D point using a matrix - */ -static void xformpnt(float matrix[4][4], float x, float y, float z, float* tx, float* ty, float* tz) -{ - *tx = x * matrix[0][0] + y * matrix[1][0] + z * matrix[2][0] + matrix[3][0]; - *ty = x * matrix[0][1] + y * matrix[1][1] + z * matrix[2][1] + matrix[3][1]; - *tz = x * matrix[0][2] + y * matrix[1][2] + z * matrix[2][2] + matrix[3][2]; -} - -/* - * cscalemat - - * make a color scale marix - */ -static void cscalemat(float mat[4][4], float rscale, float gscale, float bscale) -{ - float mmat[4][4]; - - mmat[0][0] = rscale; - mmat[0][1] = 0.0; - mmat[0][2] = 0.0; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = gscale; - mmat[1][2] = 0.0; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = 0.0; - mmat[2][2] = bscale; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * lummat - - * make a luminance marix - */ -static void lummat(float mat[4][4]) -{ - float mmat[4][4]; - float rwgt, gwgt, bwgt; - - rwgt = RLUM; - gwgt = GLUM; - bwgt = BLUM; - mmat[0][0] = rwgt; - mmat[0][1] = rwgt; - mmat[0][2] = rwgt; - mmat[0][3] = 0.0; - - mmat[1][0] = gwgt; - mmat[1][1] = gwgt; - mmat[1][2] = gwgt; - mmat[1][3] = 0.0; - - mmat[2][0] = bwgt; - mmat[2][1] = bwgt; - mmat[2][2] = bwgt; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * saturatemat - - * make a saturation marix - */ -static void saturatemat(float mat[4][4], float sat) -{ - float mmat[4][4]; - float a, b, c, d, e, f, g, h, i; - float rwgt, gwgt, bwgt; - - rwgt = RLUM; - gwgt = GLUM; - bwgt = BLUM; - - a = (1.0 - sat) * rwgt + sat; - b = (1.0 - sat) * rwgt; - c = (1.0 - sat) * rwgt; - d = (1.0 - sat) * gwgt; - e = (1.0 - sat) * gwgt + sat; - f = (1.0 - sat) * gwgt; - g = (1.0 - sat) * bwgt; - h = (1.0 - sat) * bwgt; - i = (1.0 - sat) * bwgt + sat; - mmat[0][0] = a; - mmat[0][1] = b; - mmat[0][2] = c; - mmat[0][3] = 0.0; - - mmat[1][0] = d; - mmat[1][1] = e; - mmat[1][2] = f; - mmat[1][3] = 0.0; - - mmat[2][0] = g; - mmat[2][1] = h; - mmat[2][2] = i; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * offsetmat - - * offset r, g, and b - */ -static void offsetmat(float mat[4][4], float roffset, float goffset, float boffset) -{ - float mmat[4][4]; - - mmat[0][0] = 1.0; - mmat[0][1] = 0.0; - mmat[0][2] = 0.0; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = 1.0; - mmat[1][2] = 0.0; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = 0.0; - mmat[2][2] = 1.0; - mmat[2][3] = 0.0; - - mmat[3][0] = roffset; - mmat[3][1] = goffset; - mmat[3][2] = boffset; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * xrotate - - * rotate about the x (red) axis - */ -inline void xrotatemat(float mat[4][4], float rs, float rc) -{ - float mmat[4][4]; - - mmat[0][0] = 1.0; - mmat[0][1] = 0.0; - mmat[0][2] = 0.0; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = rc; - mmat[1][2] = rs; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = -rs; - mmat[2][2] = rc; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * yrotate - - * rotate about the y (green) axis - */ -static void yrotatemat(float mat[4][4], float rs, float rc) -{ - float mmat[4][4]; - - mmat[0][0] = rc; - mmat[0][1] = 0.0; - mmat[0][2] = -rs; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = 1.0; - mmat[1][2] = 0.0; - mmat[1][3] = 0.0; - - mmat[2][0] = rs; - mmat[2][1] = 0.0; - mmat[2][2] = rc; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * zrotate - - * rotate about the z (blue) axis - */ -static void zrotatemat(float mat[4][4], float rs, float rc) -{ - float mmat[4][4]; - - mmat[0][0] = rc; - mmat[0][1] = rs; - mmat[0][2] = 0.0; - mmat[0][3] = 0.0; - - mmat[1][0] = -rs; - mmat[1][1] = rc; - mmat[1][2] = 0.0; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = 0.0; - mmat[2][2] = 1.0; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * zshear - - * shear z using x and y. - */ -static void zshearmat(float mat[4][4], float dx, float dy) -{ - float mmat[4][4]; - - mmat[0][0] = 1.0; - mmat[0][1] = 0.0; - mmat[0][2] = dx; - mmat[0][3] = 0.0; - - mmat[1][0] = 0.0; - mmat[1][1] = 1.0; - mmat[1][2] = dy; - mmat[1][3] = 0.0; - - mmat[2][0] = 0.0; - mmat[2][1] = 0.0; - mmat[2][2] = 1.0; - mmat[2][3] = 0.0; - - mmat[3][0] = 0.0; - mmat[3][1] = 0.0; - mmat[3][2] = 0.0; - mmat[3][3] = 1.0; - matrixmult(mmat, mat, mat); -} - -/* - * simplehuerotatemat - - * simple hue rotation. This changes luminance - */ -static void simplehuerotatemat(float mat[4][4], float rot) -{ - // log("************* simplehuerotatemat"); - - float mag; - float xrs, xrc; - float yrs, yrc; - float zrs, zrc; - identmat((float*)mat); - - /* rotate the grey vector into positive Z */ - mag = sqrt(2.0); - xrs = 1.0 / mag; - xrc = 1.0 / mag; - xrotatemat(mat, xrs, xrc); - // printmat(mat); - - mag = sqrt(3.0); - yrs = -1.0 / mag; - yrc = sqrt(2.0) / mag; - yrotatemat(mat, yrs, yrc); - // printmat(mat); - - /* rotate the hue */ - zrs = sin(rot); - zrc = cos(rot); - zrotatemat(mat, zrs, zrc); - // printmat(mat); - - /* rotate the grey vector back into place */ - yrotatemat(mat, -yrs, yrc); - // printmat(mat); - xrotatemat(mat, -xrs, xrc); - // printmat(mat); - - // log("############## simplehuerotatemat"); -} - -/* - * huerotatemat - - * rotate the hue, while maintaining luminance. - */ -static void huerotatemat(float mat[4][4], float rot) -{ - float mmat[4][4]; - float mag; - float lx, ly, lz; - float xrs, xrc; - float yrs, yrc; - float zrs, zrc; - float zsx, zsy; - - identmat((float*)mat); - identmat((float*)&mmat); - - /* rotate the grey vector into positive Z */ - mag = sqrt(2.0); - xrs = 1.0 / mag; - xrc = 1.0 / mag; - xrotatemat(mmat, xrs, xrc); - mag = sqrt(3.0); - yrs = -1.0 / mag; - yrc = sqrt(2.0) / mag; - yrotatemat(mmat, yrs, yrc); - - /* shear the space to make the luminance plane horizontal */ - xformpnt(mmat, RLUM, GLUM, BLUM, &lx, &ly, &lz); - zsx = lx / lz; - zsy = ly / lz; - zshearmat(mmat, zsx, zsy); - - /* rotate the hue */ - zrs = sin(rot); - zrc = cos(rot); - zrotatemat(mmat, zrs, zrc); - - /* unshear the space to put the luminance plane back */ - zshearmat(mmat, -zsx, -zsy); - - /* rotate the grey vector back into place */ - yrotatemat(mmat, -yrs, yrc); - xrotatemat(mmat, -xrs, xrc); - - matrixmult(mmat, mat, mat); -} - -/* - * xformpnt - - * transform a 3D point using a matrix - */ -static void xformpnt(Mat3* matrix, float x, float y, float z, float* tx, float* ty, float* tz) -{ - *tx = x * matrix->m[0] + y * matrix->m[3] + z * matrix->m[6]; - *ty = x * matrix->m[1] + y * matrix->m[4] + z * matrix->m[7]; - *tz = x * matrix->m[2] + y * matrix->m[5] + z * matrix->m[8]; -} - -/* - * zshear - - * shear z using x and y. - */ -static void zshearmat(Mat3* mat, float dx, float dy) -{ - // float mmat[4][4]; - Mat3 mmat; - // mmat[0][0] = 1.0; - // mmat[0][1] = 0.0; - mmat.m[2] = dx; - // mmat[0][3] = 0.0; - - // mmat[1][0] = 0.0; - // mmat[1][1] = 1.0; - mmat.m[5] = dy; - // mmat[1][3] = 0.0; - - // mmat[2][0] = 0.0; - // mmat[2][1] = 0.0; - // mmat[2][2] = 1.0; - // mmat[2][3] = 0.0; - - // mmat[3][0] = 0.0; - // mmat[3][1] = 0.0; - // mmat[3][2] = 0.0; - // mmat[3][3] = 1.0; - mat->mult(mmat); // matrixmult(mmat, mat, mat); -} - -static void createHueMatrix(Mat4* dst, float angle) -{ - // log("************* createHueMatrix4f"); - - memcpy(dst, &dst->IDENTITY, sizeof(*dst)); - - /* rotate the grey vector into positive Z */ - createRotationX(dst, FLT_XRS, FLT_XRC); // rotateX(dst, FLT_XRS, FLT_XRC); - rotateY(dst, FLT_YRS, FLT_YRC); - - /* rotate the hue */ - rotateZ(dst, angle); - - /* rotate the grey vector back into place */ - rotateY(dst, -FLT_YRS, FLT_YRC); - rotateX(dst, -FLT_XRS, FLT_XRC); - - // log("############## createHueMatrix4f"); -} - -static void setMatrixHueOptimized(Mat3* dst, float angle) -{ - float lx, ly, lz; - float zsx, zsy; - // memcpy(dst, &dst->IDENTITY, sizeof(*dst)); - - /* rotate the grey vector into positive Z */ - dst->createRotationX(FLT_XRS, FLT_XRC); // rotateX(dst, FLT_XRS, FLT_XRC); - dst->rotateY(FLT_YRS, FLT_YRC); - - /* shear the space to make the luminance plane horizontal */ - xformpnt(dst, RLUM, GLUM, BLUM, &lx, &ly, &lz); - zsx = lx / lz; - zsy = ly / lz; - zshearmat(dst, zsx, zsy); - - /* rotate the hue */ - dst->rotateZ(angle); - - /* unshear the space to put the luminance plane back */ - zshearmat(dst, -zsx, -zsy); - - /* rotate the grey vector back into place */ - dst->rotateY(-FLT_YRS, FLT_YRC); - dst->rotateX(-FLT_XRS, FLT_XRC); -} - -/* - * Hue - - * HSV - H - */ -static void setMatrixHue(Mat3* dst, float angle) -{ - log("************* createHueMat3"); - - // memcpy(dst, &dst->IDENTITY, sizeof(*dst)); - - /* rotate the grey vector into positive Z */ - dst->createRotationX(FLT_XRS, FLT_XRC); // rotateX(dst, FLT_XRS, FLT_XRC); - dst->rotateY(FLT_YRS, FLT_YRC); - - /* rotate the hue */ - dst->rotateZ(angle); - - /* rotate the grey vector back into place */ - dst->rotateY(-FLT_YRS, FLT_YRC); - dst->rotateX(-FLT_XRS, FLT_XRC); - - log("############## createHueMat3"); -} - -/* - * saturatemat - 0~1, 0%~100% ? - * HSV - S - */ -static void setMatrixSat(Mat3* dst, float sat) -{ - Mat3 temp; - float a, b, c, d, e, f, g, h, i; - float rwgt, gwgt, bwgt; - - rwgt = RLUM; - gwgt = GLUM; - bwgt = BLUM; - - a = (1.0 - sat) * rwgt + sat; - b = (1.0 - sat) * rwgt; - c = (1.0 - sat) * rwgt; - d = (1.0 - sat) * gwgt; - e = (1.0 - sat) * gwgt + sat; - f = (1.0 - sat) * gwgt; - g = (1.0 - sat) * bwgt; - h = (1.0 - sat) * bwgt; - i = (1.0 - sat) * bwgt + sat; - temp.m[0] = a; - temp.m[1] = b; - temp.m[2] = c; - // mmat[0][3] = 0.0; - - temp.m[3] = d; - temp.m[4] = e; - temp.m[5] = f; - // mmat[1][3] = 0.0; - - temp.m[6] = g; - temp.m[7] = h; - temp.m[8] = i; - // mmat[2][3] = 0.0; - - // mmat[3][0] = 0.0; - // mmat[3][1] = 0.0; - // mmat[3][2] = 0.0; - // mmat[3][3] = 1.0; - // matrixmult(mmat, mat, mat); - dst->mult(temp); -} - -/* Value - * HSV - V: 0~1, 0%, 100% - */ -static void setMatrixVal(Mat3* dst, float value) -{ - // float mmat[4][4]; - Mat3 temp; - temp.m[0] = value; - // temp.m[1] = 0.0; - // temp.m[2] = 0.0; - // mmat[0][3] = 0.0; - - // mmat[1][0] = 0.0; - temp.m[4] = value; - // mmat[1][2] = 0.0; - // mmat[1][3] = 0.0; - - // mmat[2][0] = 0.0; - // mmat[2][1] = 0.0; - temp.m[8] = value; - // mmat[2][3] = 0.0; - - dst->mult(temp); - // matrixmult(mmat, mat, mat); -} - -bool Colorizer::enableNodeIntelliShading(Node* node, const Vec3& hsv, const Vec3& filter) -{ - if (node == nullptr) - return false; - - node->setProgramState(backend::ProgramType::HSV); - - updateNodeHsv(node, hsv, filter); - - return true; -} - -void Colorizer::updateNodeHsv(Node* node, const Vec3& hsv, const Vec3& filter) -{ - Mat3 hsvMatrix; - setMatrixHueOptimized(&hsvMatrix, hsv.x); - setMatrixSat(&hsvMatrix, hsv.y); - setMatrixVal(&hsvMatrix, hsv.z); - -#if CLZ_PRINTMAT - printmat3(hsvMatrix.m); -#endif - - auto programState = node->getProgramState(); - programState->setUniform(programState->getUniformLocation("u_mix_hsv"), &hsvMatrix.m[0], sizeof(hsvMatrix)); - programState->setUniform(programState->getUniformLocation("u_filter_rgb"), &filter, sizeof(filter)); - programState->hashOfUniforms(); -} - -NS_AX_END diff --git a/core/renderer/Colorizer.h b/core/renderer/Colorizer.h deleted file mode 100644 index 856137a47f..0000000000 --- a/core/renderer/Colorizer.h +++ /dev/null @@ -1,23 +0,0 @@ -/** - * CCColorizer, for color translate matrix - * reference: http://graficaobscura.com/matrix/index.html - * @autohr HALX99 2020 - */ -#pragma once -#ifndef _CCCOLORIZER_H_ -# define _CCCOLORIZER_H_ -# include "math/Math.h" -# include "base/Types.h" -# include - -NS_AX_BEGIN -class AX_DLL Colorizer -{ -public: - static bool enableNodeIntelliShading(Node* node, const Vec3& hsv, const Vec3& filter = Vec3(1.0f, 0.45f, 0.3109f)); - - static void updateNodeHsv(Node* node, const Vec3& hsv, const Vec3& filter = Vec3(1.0f, 0.45f, 0.3109f)); -}; -NS_AX_END - -#endif diff --git a/core/renderer/Material.cpp b/core/renderer/Material.cpp index 50d99fb980..5304ae70bc 100644 --- a/core/renderer/Material.cpp +++ b/core/renderer/Material.cpp @@ -367,24 +367,12 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties) // fragmentShader const char* fragShader = getOptionalString(shaderProperties, "fragmentShader", nullptr); - // compileTimeDefines - const char* compileTimeDefines = getOptionalString(shaderProperties, "defines", ""); - - auto* fu = FileUtils::getInstance(); + // compileTimeDefines, since axmol-1.1 no longer support compile time defines + // const char* compileTimeDefines = getOptionalString(shaderProperties, "defines", ""); if (vertShader && fragShader) { - - auto vertShaderSrc = fu->getStringFromFile(vertShader); - auto fragShaderSrc = fu->getStringFromFile(fragShader); - - //since axmol-1.1 no longer support compile time defines - //auto defs = replaceDefines(compileTimeDefines); - - //vertShaderSrc = defs + "\n" + vertShaderSrc; - //fragShaderSrc = defs + "\n" + fragShaderSrc; - - auto* program = backend::Device::getInstance()->newProgram(vertShaderSrc, fragShaderSrc); + auto program = ProgramManager::getInstance()->loadProgram(vertShader, fragShader); auto programState = new backend::ProgramState(program); pass->setProgramState(programState); @@ -410,8 +398,7 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties) } space = shaderProperties->getNextNamespace(); } - AX_SAFE_RELEASE(program); - AX_SAFE_RELEASE(programState); + programState->release(); } return true; diff --git a/core/renderer/Shaders.cpp b/core/renderer/Shaders.cpp index 434b8295d3..f44e8c2d0b 100644 --- a/core/renderer/Shaders.cpp +++ b/core/renderer/Shaders.cpp @@ -62,8 +62,8 @@ AX_DLL const std::string_view hsv_frag = "hsv_fs"sv; AX_DLL const std::string_view dualSampler_hsv_frag = "dualSampler_hsv_fs"sv; AX_DLL const std::string_view videoTextureYUY2_frag = "videoTextureYUY2_fs"sv; AX_DLL const std::string_view videoTextureNV12_frag = "videoTextureNV12_fs"sv; -AX_DLL const std::string_view lineColor3D_frag = "lineColor3D_fs"sv; -AX_DLL const std::string_view lineColor3D_vert = "lineColor3D_vs"sv; +AX_DLL const std::string_view lineColor_frag = "lineColor_fs"sv; +AX_DLL const std::string_view lineColor_vert = "lineColor_vs"sv; AX_DLL const std::string_view color_frag = "color_fs"sv; AX_DLL const std::string_view colorNormal_frag = "colorNormal_fs"sv; AX_DLL const std::string_view colorNormalTexture_frag = "colorNormalTexture_fs"sv; diff --git a/core/renderer/Shaders.h b/core/renderer/Shaders.h index f0cdeb29f7..ca65d118f7 100644 --- a/core/renderer/Shaders.h +++ b/core/renderer/Shaders.h @@ -75,8 +75,8 @@ extern AX_DLL const std::string_view videoTextureYUY2_frag; extern AX_DLL const std::string_view videoTextureNV12_frag; /* below is 3d shaders */ -extern AX_DLL const std::string_view lineColor3D_frag; -extern AX_DLL const std::string_view lineColor3D_vert; +extern AX_DLL const std::string_view lineColor_frag; +extern AX_DLL const std::string_view lineColor_vert; extern AX_DLL const std::string_view color_frag; extern AX_DLL const std::string_view colorNormal_frag; extern AX_DLL const std::string_view colorNormalTexture_frag; diff --git a/core/renderer/TrianglesCommand.cpp b/core/renderer/TrianglesCommand.cpp index b3238799e4..22e6a1dc0c 100644 --- a/core/renderer/TrianglesCommand.cpp +++ b/core/renderer/TrianglesCommand.cpp @@ -53,15 +53,16 @@ void TrianglesCommand::init(float globalOrder, } _mv = mv; - auto programType = _pipelineDescriptor.programState->getProgram()->getProgramType(); - auto uniformID = _pipelineDescriptor.programState->hashOfUniforms(); - if (_programType != programType || _texture != texture->getBackendTexture() || _blendType != blendType || - _uniformID != uniformID) + auto batchId = _pipelineDescriptor.programState->getBatchId(); + if (_batchId != batchId || _texture != texture->getBackendTexture() || _blendType != blendType) { - _programType = programType; - _texture = texture->getBackendTexture(); - _blendType = blendType; - _uniformID = uniformID; + _batchId = batchId; + _texture = texture->getBackendTexture(); + _blendType = blendType; + + // since it would be too expensive to check the uniforms, simplify enable batching for built-in program. + // if (_programType == backend::ProgramType::CUSTOM_PROGRAM) + // setSkipBatching(true); // TODO: minggo set it in Node? auto& blendDescriptor = _pipelineDescriptor.blendDescriptor; @@ -87,8 +88,7 @@ void TrianglesCommand::generateMaterialID() struct { void* texture; - uint32_t programType; - uint32_t uniformID; + uint64_t batchId; backend::BlendFactor src; backend::BlendFactor dst; } hashMe; @@ -98,12 +98,11 @@ void TrianglesCommand::generateMaterialID() // are set to random values by different compilers. memset(&hashMe, 0, sizeof(hashMe)); - hashMe.texture = _texture; - hashMe.src = _blendType.src; - hashMe.dst = _blendType.dst; - hashMe.programType = _programType; - hashMe.uniformID = _uniformID; - _materialID = XXH32((const void*)&hashMe, sizeof(hashMe), 0); + hashMe.texture = _texture; + hashMe.src = _blendType.src; + hashMe.dst = _blendType.dst; + hashMe.batchId = _batchId; + _materialID = XXH32((const void*)&hashMe, sizeof(hashMe), 0); } NS_AX_END diff --git a/core/renderer/TrianglesCommand.h b/core/renderer/TrianglesCommand.h index b7a70b2e01..d88c5a828a 100644 --- a/core/renderer/TrianglesCommand.h +++ b/core/renderer/TrianglesCommand.h @@ -117,8 +117,7 @@ protected: // Cached value to determine to generate material id or not. BlendFunc _blendType = BlendFunc::DISABLE; - uint32_t _programType = backend::ProgramType::CUSTOM_PROGRAM; - uint32_t _uniformID = 0; + uint64_t _batchId = 0; backend::TextureBackend* _texture = nullptr; }; diff --git a/core/renderer/backend/Enums.h b/core/renderer/backend/Enums.h index ff7c0c4048..d01c79a00d 100644 --- a/core/renderer/backend/Enums.h +++ b/core/renderer/backend/Enums.h @@ -360,7 +360,7 @@ struct ProgramType LABEL_DISTANCE_NORMAL, // positionTextureColor_vert, label_distanceNormal_frag LABEL_DISTANCE_OUTLINE, // positionTextureColor_vert, label_distanceOutline_frag LABLE_DISTANCE_GLOW, // positionTextureColor_vert, label_distanceGlow_frag - + LAYER_RADIA_GRADIENT, // position_vert, layer_radialGradient_frag DUAL_SAMPLER, @@ -394,12 +394,13 @@ struct ProgramType VIDEO_TEXTURE_YUY2, VIDEO_TEXTURE_NV12, VIDEO_TEXTURE_BGR32, - + BUILTIN_COUNT, VIDEO_TEXTURE_RGB32 = POSITION_TEXTURE_COLOR, - CUSTOM_PROGRAM = 0x1000, // user-define program, used by engine + CUSTOM_PROGRAM = 0x1000, // user-define program, used by engine }; }; + NS_AX_BACKEND_END diff --git a/core/renderer/backend/Program.cpp b/core/renderer/backend/Program.cpp index caef7d96f7..cb8d3a3347 100644 --- a/core/renderer/backend/Program.cpp +++ b/core/renderer/backend/Program.cpp @@ -28,6 +28,154 @@ NS_AX_BACKEND_BEGIN + +/* + * shader vertex layout setup functions + */ +struct VertexLayoutHelper +{ + static void setupDummy(Program*) {} + static void setupTexture(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + /// a_position + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT2, 0, false); + /// a_texCoord + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, + program->getAttributeLocation(backend::Attribute::TEXCOORD), + backend::VertexFormat::FLOAT2, 2 * sizeof(float), false); + + vertexLayout->setStride(4 * sizeof(float)); + } + + static void setupSprite(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + /// a_position + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT3, 0, false); + /// a_texCoord + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, + program->getAttributeLocation(backend::Attribute::TEXCOORD), + backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false); + + /// a_color + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, + program->getAttributeLocation(backend::Attribute::COLOR), + backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); + vertexLayout->setStride(sizeof(V3F_C4B_T2F)); + } + + static void setupDrawNode(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT2, 0, false); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, + program->getAttributeLocation(backend::Attribute::TEXCOORD), + backend::VertexFormat::FLOAT2, offsetof(V2F_C4B_T2F, texCoords), false); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, + program->getAttributeLocation(backend::Attribute::COLOR), + backend::VertexFormat::UBYTE4, offsetof(V2F_C4B_T2F, colors), true); + + vertexLayout->setStride(sizeof(V2F_C4B_T2F)); + } + + static void setupDrawNode3D(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT3, 0, false); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, + program->getAttributeLocation(backend::Attribute::COLOR), + backend::VertexFormat::UBYTE4, sizeof(Vec3), true); + + vertexLayout->setStride(sizeof(V3F_C4B)); + } + + static void setupSkyBox(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + auto attrNameLoc = program->getAttributeLocation(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION); + vertexLayout->setAttrib(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION, attrNameLoc, + backend::VertexFormat::FLOAT3, 0, false); + vertexLayout->setStride(sizeof(Vec3)); + } + + static void setupPU3D(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_C4F, position), false); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, + program->getAttributeLocation(backend::Attribute::TEXCOORD), + backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_C4F, uv), false); + + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, + program->getAttributeLocation(backend::Attribute::COLOR), + backend::VertexFormat::FLOAT4, offsetof(V3F_T2F_C4F, color), false); + + vertexLayout->setStride(sizeof(V3F_T2F_C4F)); + } + + static void setupPos(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT2, 0, false); + vertexLayout->setStride(sizeof(Vec2)); + } + + static void setupPosColor(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT3, 0, false); + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, + program->getAttributeLocation(backend::Attribute::COLOR), + backend::VertexFormat::FLOAT4, offsetof(V3F_C4F, colors), false); + vertexLayout->setStride(sizeof(V3F_C4F)); + } + + static void setupTerrain3D(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, + program->getAttributeLocation(backend::Attribute::POSITION), + backend::VertexFormat::FLOAT3, 0, false); + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, + program->getAttributeLocation(backend::Attribute::TEXCOORD), + backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_N3F, texcoord), false); + vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_NORMAL, + program->getAttributeLocation(backend::Attribute::NORMAL), + backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_N3F, normal), false); + vertexLayout->setStride(sizeof(V3F_T2F_N3F)); + } +}; +std::function Program::s_vertexLayoutSetupList[static_cast(VertexLayoutType::Count)] = { + VertexLayoutHelper::setupDummy, VertexLayoutHelper::setupPos, VertexLayoutHelper::setupTexture, + VertexLayoutHelper::setupSprite, VertexLayoutHelper::setupDrawNode, VertexLayoutHelper::setupDrawNode3D, + VertexLayoutHelper::setupSkyBox, VertexLayoutHelper::setupPU3D, VertexLayoutHelper::setupPosColor, + VertexLayoutHelper::setupTerrain3D +}; + Program::Program(std::string_view vs, std::string_view fs) : _vertexShader(vs), _fragmentShader(fs), _vertexLayout(new VertexLayout()) {} @@ -36,9 +184,10 @@ Program::~Program() { delete _vertexLayout; } -void Program::setProgramType(uint32_t type) +void Program::setupVertexLayout(VertexLayoutType vlt) { - _programType = type; + if (vlt < VertexLayoutType::Count) + s_vertexLayoutSetupList[static_cast(vlt)](this); } Program* Program::getBuiltinProgram(uint32_t type) @@ -46,4 +195,9 @@ Program* Program::getBuiltinProgram(uint32_t type) return ProgramManager::getInstance()->getBuiltinProgram(type); } +void Program::setProgramIds(uint32_t progType, uint64_t progId) { + _programType = progType; + _programId = progId; + _batchEnabled = _programType != ProgramType::CUSTOM_PROGRAM; +} NS_AX_BACKEND_END diff --git a/core/renderer/backend/Program.h b/core/renderer/backend/Program.h index bae3fc7e08..2c7fe1fb38 100644 --- a/core/renderer/backend/Program.h +++ b/core/renderer/backend/Program.h @@ -30,6 +30,7 @@ #include "Types.h" #include "ShaderCache.h" +#include #include #include #include @@ -40,6 +41,26 @@ class ShaderModule; class VertexLayout; class ProgramManager; +/** + * @addtogroup _backend + * @{ + */ + +enum class VertexLayoutType +{ + Unspec, // needs binding after program load + Pos, // V2F + Texture, // T2F + Sprite, // V3F_C4B_T2F posTexColor + DrawNode, // V2F_C4B_T2F + DrawNode3D, // V3F_C4B + SkyBox, // V3F + PU3D, // V3F_C4B_T2F // same with sprite, TODO: reuse spriete + posColor, // V3F_C4B + Terrain3D, // V3F_T2F_V3F + Count +}; + /** * @addtogroup _backend * @{ @@ -116,12 +137,23 @@ public: */ std::string_view getFragmentShader() const { return _fragmentShader; } + /** + * Sets the program shared vertex layout type, see: VertexLayoutType + */ + void setupVertexLayout(VertexLayoutType vlt); + /** * Get engine built-in program type. * @return The built-in program type. */ uint32_t getProgramType() const { return _programType; } + /** + * Get program id. + * @return The program id. + */ + int64_t getProgramId() const { return _programId; } + /** * Get uniform buffer size in bytes that can hold all the uniforms. * @param stage Specifies the shader stage. The symbolic constant can be either VERTEX or FRAGMENT. @@ -143,15 +175,18 @@ public: */ virtual const hlookup::string_map& getAllActiveUniformInfo(ShaderStage stage) const = 0; - /** - * Set engin built-in program type. - * @param type Specifies the program type. - */ - void setProgramType(uint32_t type); - inline VertexLayout* getVertexLayout() const { return _vertexLayout; } + /** + * Sets batch draw enabled + */ + void setBatchDrawEnabled(bool enabled) { _batchEnabled = enabled; } + bool isBatchEnabled() const { return _batchEnabled; } + protected: + + void setProgramIds(uint32_t progType, uint64_t progId); + /** * @param vs Specifes the vertex shader source. * @param fs Specifes the fragment shader source. @@ -192,6 +227,12 @@ protected: std::string _fragmentShader; ///< Fragment shader. VertexLayout* _vertexLayout = nullptr; uint32_t _programType = ProgramType::CUSTOM_PROGRAM; ///< built-in program type, initial value is CUSTOM_PROGRAM. + uint64_t _programId = 0; + bool _batchEnabled = false; + + using VERTEX_LAYOUT_SETUP_FUNC = std::function; + + static std::function s_vertexLayoutSetupList[static_cast(VertexLayoutType::Count)]; }; // end of _backend group diff --git a/core/renderer/backend/ProgramManager.cpp b/core/renderer/backend/ProgramManager.cpp index cc447f9118..a08c23349c 100644 --- a/core/renderer/backend/ProgramManager.cpp +++ b/core/renderer/backend/ProgramManager.cpp @@ -30,20 +30,12 @@ #include "base/Macros.h" #include "base/Configuration.h" +#include "xxhash.h" + NS_AX_BACKEND_BEGIN ProgramManager* ProgramManager::_sharedProgramManager = nullptr; -Program* ProgramManager::newProgram(std::string_view vertShaderSource, - std::string_view fragShaderSource, - std::function fnSetupLayout) -{ - auto program = Device::getInstance()->newProgram(vertShaderSource, fragShaderSource); - if (program) - fnSetupLayout(program); - return program; -} - ProgramManager* ProgramManager::getInstance() { if (!_sharedProgramManager) @@ -62,8 +54,15 @@ void ProgramManager::destroyInstance() AX_SAFE_RELEASE_NULL(_sharedProgramManager); } +ProgramManager::ProgramManager() +{ + _programIdGen = XXH64_createState(); +} + ProgramManager::~ProgramManager() { + XXH64_freeState(_programIdGen); + for (auto&& program : _cachedPrograms) { AX_SAFE_RELEASE(program.second); @@ -72,139 +71,6 @@ ProgramManager::~ProgramManager() backend::ShaderCache::destroyInstance(); } -/* - * shader vertex layout setup functions - */ -void VertexLayoutHelper::setupDummy(Program*) {} -void VertexLayoutHelper::setupTexture(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - - /// a_position - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - /// a_texCoord - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, 2 * sizeof(float), false); - - vertexLayout->setStride(4 * sizeof(float)); -} - -void VertexLayoutHelper::setupSprite(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - - /// a_position - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - /// a_texCoord - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false); - - /// a_color - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); - vertexLayout->setStride(sizeof(V3F_C4B_T2F)); -} - -void VertexLayoutHelper::setupDrawNode(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V2F_C4B_T2F, texCoords), false); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::UBYTE4, offsetof(V2F_C4B_T2F, colors), true); - - vertexLayout->setStride(sizeof(V2F_C4B_T2F)); -} - -void VertexLayoutHelper::setupDrawNode3D(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::UBYTE4, sizeof(Vec3), true); - - vertexLayout->setStride(sizeof(V3F_C4B)); -} - -void VertexLayoutHelper::setupSkyBox(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - auto attrNameLoc = program->getAttributeLocation(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION); - vertexLayout->setAttribute(shaderinfos::attribute::ATTRIBUTE_NAME_POSITION, attrNameLoc, - backend::VertexFormat::FLOAT3, 0, false); - vertexLayout->setStride(sizeof(Vec3)); -} - -void VertexLayoutHelper::setupPU3D(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_C4F, position), false); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_C4F, uv), false); - - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::FLOAT4, offsetof(V3F_T2F_C4F, color), false); - - vertexLayout->setStride(sizeof(V3F_T2F_C4F)); -} - -void VertexLayoutHelper::setupPos(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - vertexLayout->setStride(sizeof(Vec2)); -} - -void VertexLayoutHelper::setupPosColor(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::FLOAT4, offsetof(V3F_C4F, colors), false); - vertexLayout->setStride(sizeof(V3F_C4F)); -} - -void VertexLayoutHelper::setupTerrain3D(Program* program) -{ - auto vertexLayout = program->getVertexLayout(); - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_N3F, texcoord), false); - vertexLayout->setAttribute(backend::ATTRIBUTE_NAME_NORMAL, - program->getAttributeLocation(backend::Attribute::NORMAL), backend::VertexFormat::FLOAT3, - offsetof(V3F_T2F_N3F, normal), false); - vertexLayout->setStride(sizeof(V3F_T2F_N3F)); -} - // ### end of vertex layout setup functions static std::string joinPath(std::string_view path, std::string_view childPath) { @@ -227,70 +93,62 @@ bool ProgramManager::init() #endif registerProgram(ProgramType::POSITION_TEXTURE_COLOR, positionTextureColor_vert, positionTextureColor_frag, - VertexLayoutHelper::setupSprite); - registerProgram(ProgramType::DUAL_SAMPLER, positionTextureColor_vert, dualSampler_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); + registerProgram(ProgramType::DUAL_SAMPLER, positionTextureColor_vert, dualSampler_frag, VertexLayoutType::Sprite); registerProgram(ProgramType::LABEL_DISTANCE_NORMAL, positionTextureColor_vert, label_distanceNormal_frag, - VertexLayoutHelper::setupSprite); - registerProgram(ProgramType::LABEL_NORMAL, positionTextureColor_vert, label_normal_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); + registerProgram(ProgramType::LABEL_NORMAL, positionTextureColor_vert, label_normal_frag, VertexLayoutType::Sprite); registerProgram(ProgramType::LABLE_OUTLINE, positionTextureColor_vert, label_outline_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); registerProgram(ProgramType::LABEL_DISTANCE_OUTLINE, positionTextureColor_vert, label_distanceOutline_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); registerProgram(ProgramType::LABLE_DISTANCE_GLOW, positionTextureColor_vert, label_distanceGlow_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); registerProgram(ProgramType::POSITION_COLOR_LENGTH_TEXTURE, positionColorLengthTexture_vert, - positionColorLengthTexture_frag, VertexLayoutHelper::setupDrawNode); + positionColorLengthTexture_frag, VertexLayoutType::DrawNode); registerProgram(ProgramType::POSITION_COLOR_TEXTURE_AS_POINTSIZE, positionColorTextureAsPointsize_vert, - positionColor_frag, VertexLayoutHelper::setupDrawNode); - registerProgram(ProgramType::POSITION_COLOR, positionColor_vert, positionColor_frag, - VertexLayoutHelper::setupPosColor); - registerProgram(ProgramType::LAYER_RADIA_GRADIENT, position_vert, layer_radialGradient_frag, - VertexLayoutHelper::setupPos); + positionColor_frag, VertexLayoutType::DrawNode); + registerProgram(ProgramType::POSITION_COLOR, positionColor_vert, positionColor_frag, VertexLayoutType::posColor); + registerProgram(ProgramType::LAYER_RADIA_GRADIENT, position_vert, layer_radialGradient_frag, VertexLayoutType::Pos); registerProgram(ProgramType::POSITION_TEXTURE, positionTexture_vert, positionTexture_frag, - VertexLayoutHelper::setupTexture); + VertexLayoutType::Texture); registerProgram(ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST, positionTextureColor_vert, - positionTextureColorAlphaTest_frag, VertexLayoutHelper::setupSprite); - registerProgram(ProgramType::POSITION_UCOLOR, positionUColor_vert, positionColor_frag, - VertexLayoutHelper::setupPos); + positionTextureColorAlphaTest_frag, VertexLayoutType::Sprite); + registerProgram(ProgramType::POSITION_UCOLOR, positionUColor_vert, positionColor_frag, VertexLayoutType::Pos); registerProgram(ProgramType::DUAL_SAMPLER_GRAY, positionTextureColor_vert, dualSampler_gray_frag, - VertexLayoutHelper::setupSprite); - registerProgram(ProgramType::GRAY_SCALE, positionTextureColor_vert, grayScale_frag, - VertexLayoutHelper::setupSprite); - registerProgram(ProgramType::LINE_COLOR_3D, lineColor3D_vert, lineColor3D_frag, - VertexLayoutHelper::setupDrawNode3D); - registerProgram(ProgramType::CAMERA_CLEAR, cameraClear_vert, cameraClear_frag, VertexLayoutHelper::setupSprite); - registerProgram(ProgramType::SKYBOX_3D, skybox_vert, skybox_frag, VertexLayoutHelper::setupSkyBox); + VertexLayoutType::Sprite); + registerProgram(ProgramType::GRAY_SCALE, positionTextureColor_vert, grayScale_frag, VertexLayoutType::Sprite); + registerProgram(ProgramType::LINE_COLOR_3D, lineColor_vert, lineColor_frag, VertexLayoutType::DrawNode3D); + registerProgram(ProgramType::CAMERA_CLEAR, cameraClear_vert, cameraClear_frag, VertexLayoutType::Sprite); + registerProgram(ProgramType::SKYBOX_3D, skybox_vert, skybox_frag, VertexLayoutType::SkyBox); registerProgram(ProgramType::SKINPOSITION_TEXTURE_3D, skinPositionTexture_vert, colorTexture_frag, - VertexLayoutHelper::setupDummy); + VertexLayoutType::Unspec); registerProgram(ProgramType::SKINPOSITION_NORMAL_TEXTURE_3D, skinPositionNormalTexture_vert, - colorNormalTexture_frag, VertexLayoutHelper::setupDummy); + colorNormalTexture_frag, VertexLayoutType::Unspec); registerProgram(ProgramType::POSITION_NORMAL_TEXTURE_3D, positionNormalTexture_vert, colorNormalTexture_frag, - VertexLayoutHelper::setupDummy); + VertexLayoutType::Unspec); registerProgram(ProgramType::POSITION_TEXTURE_3D, positionTexture3D_vert, colorTexture_frag, - VertexLayoutHelper::setupDummy); - registerProgram(ProgramType::POSITION_3D, positionTexture3D_vert, color_frag, VertexLayoutHelper::setupSprite); + VertexLayoutType::Unspec); + registerProgram(ProgramType::POSITION_3D, positionTexture3D_vert, color_frag, VertexLayoutType::Sprite); registerProgram(ProgramType::POSITION_NORMAL_3D, positionNormalTexture_vert, colorNormal_frag, - VertexLayoutHelper::setupDummy); + VertexLayoutType::Unspec); registerProgram(ProgramType::POSITION_BUMPEDNORMAL_TEXTURE_3D, positionNormalTexture_vert_1, - colorNormalTexture_frag_1, VertexLayoutHelper::setupDummy); + colorNormalTexture_frag_1, VertexLayoutType::Unspec); registerProgram(ProgramType::SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D, skinPositionNormalTexture_vert_1, - colorNormalTexture_frag_1, VertexLayoutHelper::setupDummy); - registerProgram(ProgramType::TERRAIN_3D, terrain_vert, terrain_frag, VertexLayoutHelper::setupTerrain3D); - registerProgram(ProgramType::PARTICLE_TEXTURE_3D, particle_vert, particleTexture_frag, - VertexLayoutHelper::setupPU3D); - registerProgram(ProgramType::PARTICLE_COLOR_3D, particle_vert, particleColor_frag, VertexLayoutHelper::setupPU3D); - registerProgram(ProgramType::QUAD_COLOR_2D, quadColor_vert, quadColor_frag, VertexLayoutHelper::setupDummy); - registerProgram(ProgramType::QUAD_TEXTURE_2D, quadTexture_vert, quadTexture_frag, VertexLayoutHelper::setupDummy); - registerProgram(ProgramType::HSV, positionTextureColor_vert, hsv_frag, VertexLayoutHelper::setupSprite); + colorNormalTexture_frag_1, VertexLayoutType::Unspec); + registerProgram(ProgramType::TERRAIN_3D, terrain_vert, terrain_frag, VertexLayoutType::Terrain3D); + registerProgram(ProgramType::PARTICLE_TEXTURE_3D, particle_vert, particleTexture_frag, VertexLayoutType::PU3D); + registerProgram(ProgramType::PARTICLE_COLOR_3D, particle_vert, particleColor_frag, VertexLayoutType::PU3D); + registerProgram(ProgramType::QUAD_COLOR_2D, quadColor_vert, quadColor_frag, VertexLayoutType::Unspec); + registerProgram(ProgramType::QUAD_TEXTURE_2D, quadTexture_vert, quadTexture_frag, VertexLayoutType::Unspec); + registerProgram(ProgramType::HSV, positionTextureColor_vert, hsv_frag, VertexLayoutType::Sprite); registerProgram(ProgramType::HSV_DUAL_SAMPLER, positionTextureColor_vert, dualSampler_hsv_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); registerProgram(ProgramType::VIDEO_TEXTURE_YUY2, positionTextureColor_vert, videoTextureYUY2_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); registerProgram(ProgramType::VIDEO_TEXTURE_NV12, positionTextureColor_vert, videoTextureNV12_frag, - VertexLayoutHelper::setupSprite); + VertexLayoutType::Sprite); // The builtin dual sampler shader registry ProgramStateRegistry::getInstance()->registerProgram(ProgramType::POSITION_TEXTURE_COLOR, @@ -304,111 +162,117 @@ bool ProgramManager::init() return true; } -Program* ProgramManager::getCustomProgram(uint32_t type) const +Program* ProgramManager::getBuiltinProgram(uint32_t type) { - return getBuiltinProgram(type | ProgramType::CUSTOM_PROGRAM); + assert(type < ProgramType::BUILTIN_COUNT); + + auto& info = _builtinRegistry[static_cast(type)]; + return loadProgram(info.vsName, info.fsName, type, static_cast(type), info.vlt); } -Program* ProgramManager::getBuiltinProgram(uint32_t type) const +Program* ProgramManager::loadProgram(uint64_t progId) { - auto iter = _cachedPrograms.find(type); - if (iter != _cachedPrograms.end()) - return iter->second; + if (progId < ProgramType::BUILTIN_COUNT) + return getBuiltinProgram(static_cast(progId)); - return addProgram(type); + auto it = _customRegistry.find(progId); + if (it != _customRegistry.end()) + return loadProgram(it->second.vsName, it->second.fsName, ProgramType::CUSTOM_PROGRAM, progId, it->second.vlt); + return nullptr; } -Program* ProgramManager::addProgram(uint32_t internalType) const +Program* ProgramManager::loadProgram(std::string_view vsName, std::string_view fsName, VertexLayoutType vlt) { - Program* program = nullptr; - if (internalType < ProgramType::BUILTIN_COUNT) - { - auto& func = _builtinRegistry[internalType]; - if (func) - program = func(); - } - else - { - auto iter = _customRegistry.find(internalType); - if (iter != _customRegistry.end()) - { - auto& func = iter->second; - if (func) - program = func(); - } - } + return loadProgram(vsName, fsName, ProgramType::CUSTOM_PROGRAM, computeProgramId(vsName, fsName), vlt); +} + +Program* ProgramManager::loadProgram(std::string_view vsName, + std::string_view fsName, + uint32_t progType, + uint64_t progId, + VertexLayoutType vlt) +{ + assert(!vsName.empty() && !fsName.empty()); + + auto it = _cachedPrograms.find(progId); + if (it != _cachedPrograms.end()) + return it->second; + + auto fileUtils = FileUtils::getInstance(); + auto vertFile = fileUtils->fullPathForFilename(vsName); + auto fragFile = fileUtils->fullPathForFilename(fsName); + auto vertSource = fileUtils->getStringFromFile(vertFile); + auto fragSource = fileUtils->getStringFromFile(fragFile); + auto program = backend::Device::getInstance()->newProgram(vertSource, fragSource); if (program) { - program->setProgramType(internalType); - _cachedPrograms.emplace(internalType, program); + program->setProgramIds(progType, progId); + if (vlt < VertexLayoutType::Count) + program->setupVertexLayout(vlt); + _cachedPrograms.emplace(progId, program); } - return program; } -bool ProgramManager::registerCustomProgram(uint32_t type, - std::string_view vsName, - std::string_view fsName, - std::function fnSetupLayout, bool force) +uint64_t ProgramManager::registerCustomProgram(std::string_view vsName, + std::string_view fsName, + VertexLayoutType vlt, + bool force) { - auto internalType = ProgramType::CUSTOM_PROGRAM | type; - return registerProgram(internalType, vsName, fsName, std::move(fnSetupLayout), force); + return registerProgram(ProgramType::CUSTOM_PROGRAM, vsName, fsName, vlt, force); } -bool ProgramManager::registerProgram(uint32_t internalType, - std::string_view vertShaderName, - std::string_view fragShaderName, - std::function fnSetupLayout, - bool force) +uint64_t ProgramManager::registerProgram(uint32_t progType, + std::string_view vsName, + std::string_view fsName, + VertexLayoutType vlt, + bool force) { - auto loadShaderFunc = [vsName = std::string{vertShaderName}, fsName = std::string{fragShaderName}, - setupLayout = std::move(fnSetupLayout)]() mutable { - auto fileUtils = FileUtils::getInstance(); - auto vertFile = fileUtils->fullPathForFilename(vsName); - auto fragFile = fileUtils->fullPathForFilename(fsName); - auto vertSource = fileUtils->getStringFromFile(vertFile); - auto fragSource = fileUtils->getStringFromFile(fragFile); - auto program = backend::Device::getInstance()->newProgram(vertSource, fragSource); - setupLayout(program); - return program; - }; - - bool ret = true; - if (internalType < ProgramType::BUILTIN_COUNT) - _builtinRegistry[internalType] = loadShaderFunc; + uint64_t progId = 0; + if (progType < ProgramType::BUILTIN_COUNT) + { + _builtinRegistry[static_cast(progType)] = {vsName, fsName, vlt}; + progId = progType; + } else { - auto it = _customRegistry.find(internalType); + progId = computeProgramId(vsName, fsName); + auto it = _customRegistry.find(progId); if (it == _customRegistry.end()) - _customRegistry.emplace(internalType, loadShaderFunc); - else if (ret = force) - it->second = loadShaderFunc; + _customRegistry.emplace(progId, BuiltinRegInfo{vsName, fsName, vlt}); + else if (force) + it->second = BuiltinRegInfo{vsName, fsName, vlt}; + else + progId = 0; } - return ret; + return progId; } -void ProgramManager::removeProgram(Program* program) +uint64_t ProgramManager::computeProgramId(std::string_view vsName, std::string_view fsName) +{ + XXH64_reset(_programIdGen, 0); + XXH64_update(_programIdGen, vsName.data(), vsName.length()); + XXH64_update(_programIdGen, fsName.data(), fsName.length()); + return XXH64_digest(_programIdGen); +} + +void ProgramManager::unloadProgram(Program* program) { if (!program) { return; } - for (auto it = _cachedPrograms.cbegin(); it != _cachedPrograms.cend();) + auto it = _cachedPrograms.find(program->_programId); + if (it != _cachedPrograms.end()) { - if (it->second == program) - { - it->second->release(); - it = _cachedPrograms.erase(it); - break; - } - else - ++it; + it->second->release(); + _cachedPrograms.erase(it); } } -void ProgramManager::removeUnusedProgram() +void ProgramManager::unloadUnusedPrograms() { for (auto iter = _cachedPrograms.cbegin(); iter != _cachedPrograms.cend();) { @@ -426,7 +290,7 @@ void ProgramManager::removeUnusedProgram() } } -void ProgramManager::removeAllPrograms() +void ProgramManager::unloadAllPrograms() { ProgramStateRegistry::getInstance()->clearPrograms(); for (auto&& program : _cachedPrograms) diff --git a/core/renderer/backend/ProgramManager.h b/core/renderer/backend/ProgramManager.h index 2110a80821..020157ec1c 100644 --- a/core/renderer/backend/ProgramManager.h +++ b/core/renderer/backend/ProgramManager.h @@ -32,40 +32,23 @@ #include #include - +#include #include "ProgramStateRegistry.h" +struct XXH64_state_s; + NS_AX_BACKEND_BEGIN /** * @addtogroup _backend * @{ */ -struct AX_DLL VertexLayoutHelper -{ - static void setupDummy(Program*); - static void setupPos(Program*); - static void setupTexture(Program*); - static void setupSprite(Program*); - static void setupDrawNode(Program*); - static void setupDrawNode3D(Program*); - static void setupSkyBox(Program*); - static void setupPU3D(Program*); - static void setupPosColor(Program*); - static void setupTerrain3D(Program*); -}; - /** * Cache and reuse program object. */ class AX_DLL ProgramManager : public Ref { public: - /** new progrma with vertexLayout setup support, user should use this API */ - static Program* newProgram(std::string_view vertShaderSource, - std::string_view fragShaderSource, - std::function fnSetupLayout = VertexLayoutHelper::setupDummy); - /** returns the shared instance */ static ProgramManager* getInstance(); @@ -73,36 +56,73 @@ public: static void destroyInstance(); /// get built-in program - Program* getBuiltinProgram(uint32_t type) const; + Program* getBuiltinProgram(uint32_t type); - // get custom program, should call registerCustomProgram first - Program* getCustomProgram(uint32_t type) const; + /* + * register a custom program + * @returns + * the id of custom program, 0: fail, the id can use by loadProgram + */ + uint64_t registerCustomProgram(std::string_view vsName, + std::string_view fsName, + VertexLayoutType vlt = VertexLayoutType::Unspec, + bool force = false); - // register custom program create factory, if custom programType already registered, will failed - bool registerCustomProgram(uint32_t type, - std::string_view vsName, - std::string_view fsName, - std::function fnSetupLayout = VertexLayoutHelper::setupDummy, - bool force = false); + /* + * load a builtin/or custom program: + * @param id: the id of program to load, the id value returned by registerCustomProgram + * or builtin programType, whe the id < ProgramType:BUILTIN_COUNT, this function + * is identical to 'getBuiltinProgram' + */ + Program* loadProgram(uint64_t progId); + + /* + * load a program with vsName, fsName as CUSTOM immediately without register + * @params + * @param vsName: the vertex shader name: custom/xxx_vs + * @param fsName: the fragment shader name: custom/xxx_vs + * @param vlt: the builtin vertex layout type used for loading program + * @returns Program* (nullable) + * @remark: the returend program type always ProgramType::CUSTOM_PROGRAM + */ + Program* loadProgram(std::string_view vsName, + std::string_view fsName, + VertexLayoutType vlt = VertexLayoutType::Unspec); + + /** + * Unload a program object from cache. + * @param program Specifies the program object to move. + */ + void unloadProgram(Program* program); + + /** + * Unload all unused program objects from cache. + */ + void unloadUnusedPrograms(); + + /** + * Unload all program objects from cache. + */ + void unloadAllPrograms(); /** * Remove a program object from cache. * @param program Specifies the program object to move. */ - void removeProgram(Program* program); + AX_DEPRECATED_ATTRIBUTE void removeProgram(Program* prog) { unloadProgram(prog); } /** * Remove all unused program objects from cache. */ - void removeUnusedProgram(); + AX_DEPRECATED_ATTRIBUTE void removeUnusedProgram() { unloadUnusedPrograms(); } /** * Remove all program objects from cache. */ - void removeAllPrograms(); + AX_DEPRECATED_ATTRIBUTE void removeAllPrograms() { unloadAllPrograms(); } protected: - ProgramManager() = default; + ProgramManager(); virtual ~ProgramManager(); /** @@ -110,18 +130,41 @@ protected: */ bool init(); - bool registerProgram(uint32_t internalType, - std::string_view vsName, - std::string_view fsName, - std::function fnSetupLayout, - bool force = false); - Program* addProgram(uint32_t internalType) const; + /** + * register a program + */ + uint64_t registerProgram(uint32_t progType, + std::string_view vsName, + std::string_view fsName, + VertexLayoutType vlt, + bool force = false); - std::function _builtinRegistry[(int)backend::ProgramType::BUILTIN_COUNT]; - std::unordered_map> _customRegistry; + /** + * load a custom program by vsName, fsName, vertexLayout + */ + Program* loadProgram(std::string_view vsName, + std::string_view fsName, + uint32_t progType, + uint64_t progId, + VertexLayoutType vlt); - mutable std::unordered_map _cachedPrograms; ///< The cached program object. - static ProgramManager* _sharedProgramManager; ///< A shared instance of the program cache. + uint64_t computeProgramId(std::string_view vsName, std::string_view fsName); + + struct BuiltinRegInfo + { // builtin shader name is literal string, so use std::string_view ok + std::string_view vsName; + std::string_view fsName; + VertexLayoutType vlt; + }; + + BuiltinRegInfo _builtinRegistry[(int)backend::ProgramType::BUILTIN_COUNT]; + std::unordered_map _customRegistry; + + std::unordered_map _cachedPrograms; ///< The cached program object. + + XXH64_state_s* _programIdGen; + + static ProgramManager* _sharedProgramManager; ///< A shared instance of the program cache. }; using ProgramCache = ProgramManager; // for compatible @@ -136,11 +179,12 @@ NS_AX_BACKEND_END NS_AX_BEGIN -using ProgramType = ::ax::backend::ProgramType; -using Program = ::ax::backend::Program; -using VertexLayout = ::ax::backend::VertexLayout; -using VertexLayoutHelper = ::ax::backend::VertexLayoutHelper; -using ProgramManager = ::ax::backend::ProgramManager; -using ProgramRegistry = ::ax::backend::ProgramStateRegistry; +using ProgramType = ::ax::backend::ProgramType; +using ProgramState = ::ax::backend::ProgramState; +using Program = ::ax::backend::Program; +using VertexLayout = ::ax::backend::VertexLayout; +using VertexLayoutType = ::ax::backend::VertexLayoutType; +using ProgramManager = ::ax::backend::ProgramManager; +using ProgramRegistry = ::ax::backend::ProgramStateRegistry; NS_AX_END diff --git a/core/renderer/backend/ProgramState.cpp b/core/renderer/backend/ProgramState.cpp index 31f4c3cb1b..42750b0433 100644 --- a/core/renderer/backend/ProgramState.cpp +++ b/core/renderer/backend/ProgramState.cpp @@ -32,7 +32,6 @@ #include "base/Director.h" #include -#include "xxhash.h" #include "glslcc/sgs-spec.h" NS_AX_BACKEND_BEGIN @@ -204,9 +203,18 @@ bool ProgramState::init(Program* program) EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*) { this->resetUniforms(); }); Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, -1); #endif + + updateBatchId(); + return true; } +void ProgramState::updateBatchId() +{ + _batchId = _program->isBatchEnabled() ? _program->getProgramId() + : static_cast(reinterpret_cast(this)); +} + void ProgramState::resetUniforms() { #if AX_ENABLE_CACHE_TEXTURE_DATA @@ -257,7 +265,7 @@ ProgramState* ProgramState::clone() const #ifdef AX_USE_METAL memcpy(cp->_fragmentUniformBuffer, _fragmentUniformBuffer, _fragmentUniformBufferSize); #endif - cp->_uniformID = _uniformID; + cp->_batchId = this->_batchId; return cp; } @@ -392,8 +400,6 @@ void ProgramState::setVertexUniform(int location, const void* data, std::size_t assert(location + offset + size <= _vertexUniformBufferSize); memcpy(_vertexUniformBuffer + location + offset, data, size); #endif - - _uniformDirty = true; } void ProgramState::setFragmentUniform(int location, const void* data, std::size_t size) @@ -426,7 +432,7 @@ void ProgramState::setVertexAttrib(std::string_view name, { ensureVertexLayoutMutable(); - _vertexLayout->setAttribute(name, index, format, offset, needToBeNormallized); + _vertexLayout->setAttrib(name, index, format, offset, needToBeNormallized); } void ProgramState::setVertexStride(uint32_t stride) @@ -435,16 +441,10 @@ void ProgramState::setVertexStride(uint32_t stride) _vertexLayout->setStride(stride); } -void ProgramState::setVertexLayout(const VertexLayout& vertexLayout) -{ - ensureVertexLayoutMutable(); - *_vertexLayout = vertexLayout; -} - -void ProgramState::validateSharedVertexLayout(std::function fnValidate) +void ProgramState::validateSharedVertexLayout(VertexLayoutType vlt) { if (!_ownVertexLayout && !_vertexLayout->isValid()) - fnValidate(_program); + _program->setupVertexLayout(vlt); } void ProgramState::ensureVertexLayoutMutable() @@ -456,22 +456,21 @@ void ProgramState::ensureVertexLayoutMutable() } } -uint32_t ProgramState::hashOfUniforms() +VertexLayout* ProgramState::getMutableVertexLayout() { - if (!_uniformDirty) - return _uniformID; + if (_ownVertexLayout || !_vertexLayout->isValid()) + return _vertexLayout; - _uniformDirty = false; -#ifdef AX_USE_METAL - XXH32_reset(_uniformHashState, 0); - XXH32_update(_uniformHashState, _vertexUniformBuffer, _vertexUniformBufferSize); - XXH32_update(_uniformHashState, _fragmentUniformBuffer, _fragmentUniformBufferSize); - _uniformID = XXH32_digest(_uniformHashState); -#else - _uniformID = XXH32(_vertexUniformBuffer, _vertexUniformBufferSize, 0); -#endif + _ownVertexLayout = true; + return _vertexLayout = new VertexLayout(); +} - return _uniformID; +void ProgramState::setSharedVertexLayout(VertexLayout* vertexLayout) +{ + if (_ownVertexLayout) + delete _vertexLayout; + _ownVertexLayout = false; + _vertexLayout = vertexLayout; } void ProgramState::setTexture(backend::TextureBackend* texture) diff --git a/core/renderer/backend/ProgramState.h b/core/renderer/backend/ProgramState.h index 9e52816062..f4a6e0687f 100644 --- a/core/renderer/backend/ProgramState.h +++ b/core/renderer/backend/ProgramState.h @@ -294,32 +294,38 @@ public: inline const VertexLayout* getVertexLayout() const { return _vertexLayout; } + VertexLayout* getMutableVertexLayout(); - /** - * Updates uniformID, it's part of materialID for batch draw - * @param uniformID if not -1, will compute with uniform buffer by XXH32 algorithm and should call - * this function after any unstable uniforms set - * @remark If your custom shader uniform not stable, you needs call this function to update uniformID for - * render to generate a different materialID + void setSharedVertexLayout(VertexLayout* vertexLayout); + + /* + * Gets batch id of current program state, part of batch draw materialID + */ + uint64_t getBatchId() const { return _batchId; }; + + /* + * Update batchID of current program state, by default, custom program was traits with mutable uniforms + * so batch ID was set to address of valid ProgramState object + * If your programState not volatile, you can invoke this API to set with your custom ProgramId prog->getProgramId() + */ + void updateBatchId(); + + /* + * Follow API is deprecated, use getMutableVertexLayout instead */ - uint32_t hashOfUniforms(); - - void setVertexAttrib(std::string_view name, - std::size_t index, - VertexFormat format, - std::size_t offset, - bool needToBeNormallized); - void setVertexStride(uint32_t stride); - - void setVertexLayout(const VertexLayout& vertexLayout); + AX_DEPRECATED_ATTRIBUTE void setVertexAttrib(std::string_view name, + std::size_t index, + VertexFormat format, + std::size_t offset, + bool needToBeNormallized); + AX_DEPRECATED_ATTRIBUTE void setVertexStride(uint32_t stride); /** Custom shader program's vertex layout maybe not setup * so engine specific render node(such as Sprite) should invoke this API when ProgramState changed */ - void validateSharedVertexLayout(std::function fnValidate); + void validateSharedVertexLayout(VertexLayoutType); protected: - void ensureVertexLayoutMutable(); /** @@ -406,13 +412,9 @@ protected: static std::vector _customAutoBindingResolvers; VertexLayout* _vertexLayout = nullptr; - bool _ownVertexLayout = false; + bool _ownVertexLayout = false; - uint32_t _uniformID = 0; - bool _uniformDirty = false; -#ifdef AX_USE_METAL - struct XXH32_state_s* _uniformHashState = nullptr; -#endif + uint64_t _batchId = 0; #if AX_ENABLE_CACHE_TEXTURE_DATA EventListenerCustom* _backToForegroundListener = nullptr; diff --git a/core/renderer/backend/VertexLayout.cpp b/core/renderer/backend/VertexLayout.cpp index 079c200834..cf002c936b 100644 --- a/core/renderer/backend/VertexLayout.cpp +++ b/core/renderer/backend/VertexLayout.cpp @@ -28,7 +28,7 @@ NS_AX_BACKEND_BEGIN -void VertexLayout::setAttribute(std::string_view name, +void VertexLayout::setAttrib(std::string_view name, std::size_t index, VertexFormat format, std::size_t offset, diff --git a/core/renderer/backend/VertexLayout.h b/core/renderer/backend/VertexLayout.h index 61059b2fd8..839a7a7917 100644 --- a/core/renderer/backend/VertexLayout.h +++ b/core/renderer/backend/VertexLayout.h @@ -63,7 +63,7 @@ public: bool needToBeNormallized = false; }; - VertexLayout() = default; + VertexLayout() = default; VertexLayout(const VertexLayout&) = default; /** @@ -75,11 +75,20 @@ public: * @param needToBeNormallized Specifies whether fixed-point data values should be normalized (true) or converted * directly as fixed-point values (false) when they are accessed. */ - void setAttribute(std::string_view name, + void setAttrib(std::string_view name, + std::size_t index, + VertexFormat format, + std::size_t offset, + bool needNormalized); + + AX_DEPRECATED_ATTRIBUTE void setAttribute(std::string_view name, std::size_t index, VertexFormat format, std::size_t offset, - bool needToBeNormallized); + bool needNormalized) + { + setAttrib(name, index, format, offset, needNormalized); + } /** * Set stride of vertices. diff --git a/core/renderer/backend/opengl/ProgramGL.h b/core/renderer/backend/opengl/ProgramGL.h index 604580b447..1a086d3983 100644 --- a/core/renderer/backend/opengl/ProgramGL.h +++ b/core/renderer/backend/opengl/ProgramGL.h @@ -208,8 +208,6 @@ private: UniformLocation _builtinUniformLocation[UNIFORM_MAX]; int _builtinAttributeLocation[Attribute::ATTRIBUTE_MAX]; std::unordered_map _bufferOffset; - - uint32_t _hashOfUniforms = 0; }; // end of _opengl group /// @} diff --git a/core/renderer/shaders/colorUtils.glsl b/core/renderer/shaders/colorUtils.glsl new file mode 100644 index 0000000000..2a38ebe9e9 --- /dev/null +++ b/core/renderer/shaders/colorUtils.glsl @@ -0,0 +1,43 @@ +#ifndef M_PI +#define M_PI 3.141592654 +#endif + +/* +* transform color with HSV +* @params +* inColor: input color in rgb +* h: hue shift (in degrees) +* s: saturation multiplier (scalar) +* v: value multiplier (scalar) +* @refers +* https://beesbuzz.biz/code/16-hsv-color-transforms +* https://www.shadertoy.com/view/3syyW1 +*/ +vec3 transformHSV(vec3 inColor, vec3 hsv) +{ + float h = hsv.x; + float s = hsv.y; + float v = hsv.z; + + float vsu = v * s * cos(h * M_PI / 180.0); + float vsw = v * s * sin(h * M_PI / 180.0); + vec3 outColor = vec3( + (.299 * v + .701 * vsu + .168 * vsw) * inColor.r + (.587 * v - .587 * vsu + .330 * vsw) * inColor.g + + (.114 * v - .114 * vsu - .497 * vsw) * inColor.b, + (.299 * v - .299 * vsu - .328 * vsw) * inColor.r + (.587 * v + .413 * vsu + .035 * vsw) * inColor.g + + (.114 * v - .114 * vsu + .292 * vsw) * inColor.b, + (.299 * v - .300 * vsu + 1.25 * vsw) * inColor.r + (.587 * v - .588 * vsu - 1.05 * vsw) * inColor.g + + (.114 * v + .886 * vsu - .203 * vsw) * inColor.b + ); + return outColor; +} + +vec3 trasnformYUV(vec3 YUV, mat4 colorTransform) +{ + YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w); + return mat3( + colorTransform[0].xyz, + colorTransform[1].xyz, + colorTransform[2].xyz + ) * YUV; +} diff --git a/core/renderer/shaders/dualSampler_hsv.frag b/core/renderer/shaders/dualSampler_hsv.frag index 73f7a899d4..aa46358f4c 100644 --- a/core/renderer/shaders/dualSampler_hsv.frag +++ b/core/renderer/shaders/dualSampler_hsv.frag @@ -2,39 +2,18 @@ precision highp float; precision highp int; +#include "colorUtils.glsl" + layout(location = 0) in vec2 v_texCoord; layout(location = 1) in vec4 v_fragmentColor; layout(binding = 0) uniform sampler2D u_tex0; layout(binding = 1) uniform sampler2D u_tex1; -// HSV matrix - -// filter color RGB values - layout(std140) uniform fs_ub { - mat3 u_mix_hsv; - vec3 u_filter_rgb; + vec3 u_hsv; }; -vec3 rgb2hsv(vec3 c) -{ - vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); - vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); - - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); -} - -vec3 hsv2rgb(vec3 c) -{ - vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); - return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); -} - layout(location = 0) out vec4 FragColor; void main() @@ -42,21 +21,7 @@ void main() vec4 texColor = vec4(texture(u_tex0, v_texCoord).rgb, texture(u_tex1, v_texCoord).r); texColor.rgb *= texColor.a; // Premultiply with Alpha channel - vec3 rgbColor = u_mix_hsv * texColor.rgb; + texColor.rgb = transformHSV(texColor.rgb, u_hsv); - float sum = texColor.r + texColor.g + texColor.b; - float rv = texColor.r / sum; - float gv = texColor.g / sum; - float bv = texColor.b / sum; - if( (rv < u_filter_rgb.r && gv < u_filter_rgb.g && bv < u_filter_rgb.b) || texColor.a < 0.1) - { // color filters, resume to original color - rgbColor = texColor.rgb; - - rgbColor.r *= v_fragmentColor.a; - rgbColor.g *= v_fragmentColor.a; - rgbColor.b *= v_fragmentColor.a; - } - - rgbColor.rgb = rgbColor.rgb * v_fragmentColor.rgb; - FragColor = vec4(rgbColor, texColor.a * v_fragmentColor.a); + FragColor = texColor * v_fragmentColor; } diff --git a/core/renderer/shaders/hsv.frag b/core/renderer/shaders/hsv.frag index a6563724f7..f9c9f675cb 100644 --- a/core/renderer/shaders/hsv.frag +++ b/core/renderer/shaders/hsv.frag @@ -2,58 +2,22 @@ precision highp float; precision highp int; +#include "colorUtils.glsl" layout(location = 0) in vec2 v_texCoord; layout(location = 1) in vec4 v_fragmentColor; layout(binding = 0) uniform sampler2D u_tex0; -// HSV matrix - -// filter color RGB values - layout(std140) uniform fs_ub { - mat3 u_mix_hsv; - vec3 u_filter_rgb; + vec3 u_hsv; }; -vec3 rgb2hsv(vec3 c) -{ - vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); - vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); - - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); -} - -vec3 hsv2rgb(vec3 c) -{ - vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); - vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); - return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); -} - layout(location = 0) out vec4 FragColor; void main() -{ - vec4 pixColor = texture(u_tex0, v_texCoord); // * v_fragmentColor; - vec3 rgbColor = u_mix_hsv * pixColor.rgb; +{ + vec4 outColor = texture(u_tex0, v_texCoord); + outColor.rgb = transformHSV(outColor.rgb, u_hsv); - float sum = pixColor.r + pixColor.g + pixColor.b; - float rv = pixColor.r / sum; - float gv = pixColor.g / sum; - float bv = pixColor.b / sum; - if( (rv < u_filter_rgb.r && gv < u_filter_rgb.g && bv < u_filter_rgb.b) || pixColor.a < 0.1) - { // color filters, resume to original color - rgbColor = pixColor.rgb; - - rgbColor.r *= v_fragmentColor.a; - rgbColor.g *= v_fragmentColor.a; - rgbColor.b *= v_fragmentColor.a; - } - - rgbColor.rgb = rgbColor.rgb * v_fragmentColor.rgb; - FragColor = vec4(rgbColor, pixColor.a * v_fragmentColor.a); + FragColor = outColor * v_fragmentColor.a; } diff --git a/core/renderer/shaders/videoTextureNV12.frag b/core/renderer/shaders/videoTextureNV12.frag index b94cae22da..e05bab98dc 100644 --- a/core/renderer/shaders/videoTextureNV12.frag +++ b/core/renderer/shaders/videoTextureNV12.frag @@ -2,6 +2,7 @@ precision highp float; precision highp int; +#include "colorUtils.glsl" layout(location = 0) in vec4 v_fragmentColor; layout(location = 1) in vec2 v_texCoord; @@ -13,16 +14,6 @@ layout(std140) uniform fs_ub { mat4 colorTransform; }; -vec3 trasnformYUV(vec3 YUV) -{ - YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w); - return mat3( - colorTransform[0].xyz, - colorTransform[1].xyz, - colorTransform[2].xyz - ) * YUV; -} - layout(location = 0) out vec4 FragColor; void main() @@ -34,7 +25,7 @@ void main() /* Convert YUV to RGB */ vec4 OutColor; - OutColor.xyz = trasnformYUV(YUV); + OutColor.xyz = trasnformYUV(YUV, colorTransform); OutColor.w = 1.0; FragColor = v_fragmentColor * OutColor; diff --git a/core/renderer/shaders/videoTextureYUY2.frag b/core/renderer/shaders/videoTextureYUY2.frag index 648d91c3db..77689e5f70 100644 --- a/core/renderer/shaders/videoTextureYUY2.frag +++ b/core/renderer/shaders/videoTextureYUY2.frag @@ -2,6 +2,7 @@ precision highp float; precision highp int; +#include "colorUtils.glsl" layout(location = 0) in vec4 v_fragmentColor; layout(location = 1) in vec2 v_texCoord; @@ -13,16 +14,6 @@ layout(std140) uniform fs_ub { mat4 colorTransform; }; -vec3 trasnformYUV(vec3 YUV) -{ - YUV -= vec3(colorTransform[0].w, colorTransform[1].w, colorTransform[2].w); - return mat3( - colorTransform[0].xyz, - colorTransform[1].xyz, - colorTransform[2].xyz - ) * YUV; -} - layout(location = 0) out vec4 FragColor; void main() @@ -35,7 +26,7 @@ void main() /* Convert YUV to RGB */ vec4 OutColor; - OutColor.xyz = trasnformYUV(YUV); + OutColor.xyz = trasnformYUV(YUV, colorTransform); OutColor.w = 1.0; FragColor = v_fragmentColor * OutColor; diff --git a/extensions/ImGui/imgui_impl_ax.cpp b/extensions/ImGui/imgui_impl_ax.cpp index 49d209478d..e62e83207f 100644 --- a/extensions/ImGui/imgui_impl_ax.cpp +++ b/extensions/ImGui/imgui_impl_ax.cpp @@ -1491,9 +1491,11 @@ static bool ImGui_ImplAx_CreateDeviceObjects() static void ImGui_ImplAx_DestroyDeviceObjects() { + auto pm = ProgramManager::getInstance(); + auto bd = ImGui_ImplGlfw_GetBackendData(); - AX_SAFE_RELEASE_NULL(bd->ProgramInfo.program); - AX_SAFE_RELEASE_NULL(bd->ProgramFontInfo.program); + pm->unloadProgram(bd->ProgramInfo.program); + pm->unloadProgram(bd->ProgramFontInfo.program); ImGui_ImplAx_DestroyFontsTexture(); } @@ -1503,26 +1505,14 @@ static bool ImGui_ImplAx_createShaderPrograms() auto bd = ImGui_ImplGlfw_GetBackendData(); - enum - { - ImGuiSprite = 0xFF, - ImGuiFont = 0xFE, - }; auto pm = ProgramManager::getInstance(); - pm->registerCustomProgram(ImGuiSprite, "custom/imgui_sprite_vs"sv, ax::positionTextureColor_frag); - pm->registerCustomProgram(ImGuiFont, "custom/imgui_sprite_vs"sv, "custom/imgui_font_fs"); - AX_SAFE_RELEASE(bd->ProgramInfo.program); - AX_SAFE_RELEASE(bd->ProgramFontInfo.program); - - bd->ProgramInfo.program = pm->getCustomProgram(ImGuiSprite); - bd->ProgramFontInfo.program = pm->getCustomProgram(ImGuiFont); + bd->ProgramInfo.program = pm->loadProgram("custom/imgui_sprite_vs"sv, ax::positionTextureColor_frag); + bd->ProgramFontInfo.program = pm->loadProgram("custom/imgui_sprite_vs"sv, "custom/imgui_font_fs"); IM_ASSERT(bd->ProgramInfo.program); IM_ASSERT(bd->ProgramFontInfo.program); - AX_SAFE_RETAIN(bd->ProgramInfo.program); - AX_SAFE_RETAIN(bd->ProgramFontInfo.program); if (!bd->ProgramInfo.program || !bd->ProgramFontInfo.program) return false; @@ -1727,7 +1717,7 @@ IMGUI_IMPL_API void ImGui_ImplAx_RenderDrawData(ImDrawData* draw_data) auto& desc = cmd->getPipelineDescriptor(); desc.programState = state; // setup attributes for ImDrawVert - desc.programState->setVertexLayout(pinfo->layout); + desc.programState->setSharedVertexLayout(&pinfo->layout); desc.programState->setUniform(pinfo->projection, &bd->Projection, sizeof(Mat4)); desc.programState->setTexture(pinfo->texture, 0, tex->getBackendTexture()); // In order to composite our output buffer we need to preserve alpha diff --git a/extensions/ImGui/imgui_impl_ax_android.cpp b/extensions/ImGui/imgui_impl_ax_android.cpp index 21daba2983..9d14aa60eb 100644 --- a/extensions/ImGui/imgui_impl_ax_android.cpp +++ b/extensions/ImGui/imgui_impl_ax_android.cpp @@ -703,7 +703,7 @@ IMGUI_IMPL_API void ImGui_ImplAx_RenderDrawData(ImDrawData* draw_data) auto& desc = cmd->getPipelineDescriptor(); desc.programState = state; // setup attributes for ImDrawVert - desc.programState->setVertexLayout(pinfo->layout); + desc.programState->setSharedVertexLayout(&pinfo->layout); desc.programState->setUniform(pinfo->projection, &bd->Projection, sizeof(Mat4)); desc.programState->setTexture(pinfo->texture, 0, tex->getBackendTexture()); // In order to composite our output buffer we need to preserve alpha diff --git a/extensions/cocostudio/ActionTimeline/BoneNode.cpp b/extensions/cocostudio/ActionTimeline/BoneNode.cpp index cee5ed9336..8d4f878127 100644 --- a/extensions/cocostudio/ActionTimeline/BoneNode.cpp +++ b/extensions/cocostudio/ActionTimeline/BoneNode.cpp @@ -72,7 +72,7 @@ bool BoneNode::init() auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); auto* program = ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP? - setProgramState(new ax::backend::ProgramState(program), false); + setProgramState(new ax::backend::ProgramState(program), true); pipelineDescriptor.programState = _programState; _mvpLocation = _programState->getUniformLocation("u_MVPMatrix"sv); diff --git a/extensions/cocostudio/ActionTimeline/SkeletonNode.cpp b/extensions/cocostudio/ActionTimeline/SkeletonNode.cpp index 3a2029009c..51e194e4fc 100644 --- a/extensions/cocostudio/ActionTimeline/SkeletonNode.cpp +++ b/extensions/cocostudio/ActionTimeline/SkeletonNode.cpp @@ -53,7 +53,7 @@ bool SkeletonNode::init() auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); auto* program = ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP? - setProgramState(new ax::backend::ProgramState(program), false); + setProgramState(new ax::backend::ProgramState(program), true); pipelineDescriptor.programState = _programState; _mvpLocation = _programState->getUniformLocation("u_MVPMatrix"); diff --git a/extensions/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp b/extensions/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp index beb1b6d9de..38c3d293db 100644 --- a/extensions/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp +++ b/extensions/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp @@ -36,7 +36,9 @@ #include "WidgetReader/NodeReader/NodeReader.h" #include "flatbuffers/flatbuffers.h" -#include "renderer/Colorizer.h" + +#include "renderer/backend/ProgramManager.h" +#include "renderer/backend/ProgramState.h" USING_NS_AX; using namespace flatbuffers; @@ -326,8 +328,11 @@ void SpriteReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta auto filter = options->filter(); if (hsv != nullptr && filter != nullptr) { - Colorizer::enableNodeIntelliShading(sprite, Vec3(hsv->x(), hsv->y(), hsv->z()), - Vec3(filter->x(), filter->y(), filter->z())); + auto prog = ProgramManager::getInstance()->getBuiltinProgram(ProgramType::HSV); + auto ps = new backend::ProgramState(prog); + sprite->setProgramState(ps, true); + Vec3 axhsv{hsv->x(), hsv->y(), hsv->z()}; + ps->setUniform(ps->getUniformLocation("u_hsv"), &axhsv, sizeof(axhsv)); } } } diff --git a/extensions/spine/CMakeLists.txt b/extensions/spine/CMakeLists.txt index b74ef3f7cc..9ffda42a4e 100644 --- a/extensions/spine/CMakeLists.txt +++ b/extensions/spine/CMakeLists.txt @@ -21,4 +21,7 @@ endif() target_include_directories(${target_name} PUBLIC "runtime/include") +ax_find_shaders(${CMAKE_CURRENT_LIST_DIR}/shaders SPINE_SHADER_SOURCES) +ax_target_compile_shaders(${target_name} FILES ${SPINE_SHADER_SOURCES} CUSTOM) + setup_ax_extension_config(${target_name}) diff --git a/extensions/spine/SkeletonBatch.cpp b/extensions/spine/SkeletonBatch.cpp index a3230a7286..8ca039fbe1 100644 --- a/extensions/spine/SkeletonBatch.cpp +++ b/extensions/spine/SkeletonBatch.cpp @@ -89,8 +89,8 @@ namespace spine { { auto& currentState = command->getPipelineDescriptor().programState; #if defined(AX_VERSION) - if (currentState == nullptr || currentState->getProgram() != programState->getProgram() || - currentState->hashOfUniforms() != programState->hashOfUniforms()) + if (currentState == nullptr || + currentState->getBatchId() != programState->getBatchId()) { #else if(currentState == nullptr || currentState->getProgram() != programState->getProgram()) { diff --git a/extensions/spine/SkeletonTwoColorBatch.cpp b/extensions/spine/SkeletonTwoColorBatch.cpp index a89231d51d..2cabd598b8 100644 --- a/extensions/spine/SkeletonTwoColorBatch.cpp +++ b/extensions/spine/SkeletonTwoColorBatch.cpp @@ -47,52 +47,8 @@ using std::max; #define MAX_VERTICES 64000 #define MAX_INDICES 64000 -#define STRINGIFY(A) #A - namespace { - const char *TWO_COLOR_TINT_VERTEX_SHADER = STRINGIFY( - uniform mat4 u_PMatrix; - attribute vec4 a_position; - attribute vec4 a_color; - attribute vec4 a_color2; - attribute vec2 a_texCoords; - - \n #ifdef GL_ES\n - varying lowp vec4 v_light; - varying lowp vec4 v_dark; - varying mediump vec2 v_texCoord; - \n #else \n - varying vec4 v_light; - varying vec4 v_dark; - varying vec2 v_texCoord; - - \n #endif \n - - void main() { - v_light = a_color; - v_dark = a_color2; - v_texCoord = a_texCoords; - gl_Position = u_PMatrix * a_position; - }); - - const char *TWO_COLOR_TINT_FRAGMENT_SHADER = STRINGIFY( - \n #ifdef GL_ES\n - precision lowp float; - \n #endif \n - uniform sampler2D u_texture; - varying vec4 v_light; - varying vec4 v_dark; - varying vec2 v_texCoord; - - void main() { - vec4 texColor = texture2D(u_texture, v_texCoord); - float alpha = texColor.a * v_light.a; - gl_FragColor.a = alpha; - gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb; - }); - - std::shared_ptr __twoColorProgramState = nullptr; backend::UniformLocation __locPMatrix; backend::UniformLocation __locTexture; @@ -106,21 +62,25 @@ namespace { auto locColor = programState->getAttributeLocation("a_color"); auto locColor2 = programState->getAttributeLocation("a_color2"); - programState->setVertexAttrib("a_position", locPosition, backend::VertexFormat::FLOAT3, offsetof(spine::V3F_C4B_C4B_T2F, position), false); - programState->setVertexAttrib("a_color", locColor, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color), true); - programState->setVertexAttrib("a_color2", locColor2, backend::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color2), true); - programState->setVertexAttrib("a_texCoords", locTexcoord, backend::VertexFormat::FLOAT2, offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false); - programState->setVertexStride(sizeof(spine::V3F_C4B_C4B_T2F)); + auto vertexLayout = programState->getMutableVertexLayout(); + vertexLayout->setAttrib("a_position", locPosition, backend::VertexFormat::FLOAT3, + offsetof(spine::V3F_C4B_C4B_T2F, position), false); + vertexLayout->setAttrib("a_color", locColor, backend::VertexFormat::UBYTE4, + offsetof(spine::V3F_C4B_C4B_T2F, color), true); + vertexLayout->setAttrib("a_color2", locColor2, backend::VertexFormat::UBYTE4, + offsetof(spine::V3F_C4B_C4B_T2F, color2), true); + vertexLayout->setAttrib("a_texCoords", locTexcoord, backend::VertexFormat::FLOAT2, + offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false); + vertexLayout->setStride(sizeof(spine::V3F_C4B_C4B_T2F)); } static void initTwoColorProgramState() { if (__twoColorProgramState) { return; } - auto program = backend::Device::getInstance()->newProgram(TWO_COLOR_TINT_VERTEX_SHADER, TWO_COLOR_TINT_FRAGMENT_SHADER); + auto program = ProgramManager::getInstance()->loadProgram("custom/spineTwoColorTint_vs", + "custom/spineTwoColorTint_fs"); auto *programState = new backend::ProgramState(program); - program->release(); - updateProgramStateLayout(programState); __twoColorProgramState = std::shared_ptr(programState); diff --git a/extensions/spine/shaders/spineTwoColorTint.frag b/extensions/spine/shaders/spineTwoColorTint.frag new file mode 100644 index 0000000000..0a6c90554a --- /dev/null +++ b/extensions/spine/shaders/spineTwoColorTint.frag @@ -0,0 +1,17 @@ +#version 310 es + +precision highp float; + +uniform sampler2D u_texture; +in vec4 v_light; +in vec4 v_dark; +in vec2 v_texCoord; + +out vec4 FragColor; + +void main() { + vec4 texColor = texture(u_texture, v_texCoord); + float alpha = texColor.a * v_light.a; + FragColor.a = alpha; + FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb; +} diff --git a/extensions/spine/shaders/spineTwoColorTint.vert b/extensions/spine/shaders/spineTwoColorTint.vert new file mode 100644 index 0000000000..740fe3e5e8 --- /dev/null +++ b/extensions/spine/shaders/spineTwoColorTint.vert @@ -0,0 +1,21 @@ +#version 310 es + +in vec4 a_position; +in vec4 a_color; +in vec4 a_color2; +in vec2 a_texCoords; + +out vec4 v_light; +out vec4 v_dark; +out vec2 v_texCoord; + +layout(std140) uniform vs_ub { + mat4 u_PMatrix; +}; + +void main() { + v_light = a_color; + v_dark = a_color2; + v_texCoord = a_texCoords; + gl_Position = u_PMatrix * a_position; +} diff --git a/tests/cpp-tests/CMakeLists.txt b/tests/cpp-tests/CMakeLists.txt index 68db3d55c0..f44b1722d7 100644 --- a/tests/cpp-tests/CMakeLists.txt +++ b/tests/cpp-tests/CMakeLists.txt @@ -221,8 +221,6 @@ list(APPEND GAME_HEADER Source/SchedulerTest/SchedulerTest.h Source/MultiTouchTest/MultiTouchTest.h Source/testResource.h - Source/ShaderTest/ShaderTest.vsh.h - Source/ShaderTest/shaderTest.psh.h Source/ShaderTest/ShaderTest.h Source/ShaderTest/ShaderTest2.h Source/NewRendererTest/NewRendererTest.h diff --git a/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp b/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp index dd135da152..7ccc038797 100644 --- a/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp +++ b/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp @@ -1253,12 +1253,9 @@ void FogTestDemo::onEnter() AX_SAFE_RELEASE_NULL(_programState1); AX_SAFE_RELEASE_NULL(_programState2); - auto vertexSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.vert"); - auto fragSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.frag"); - auto program = ProgramManager::newProgram(vertexSource, fragSource); + auto program = ProgramManager::getInstance()->loadProgram("custom/fog_vs", "custom/fog_fs"); _programState1 = new backend::ProgramState(program); _programState2 = new backend::ProgramState(program); - AX_SAFE_RELEASE(program); _mesh1 = MeshRenderer::create("MeshRendererTest/teapot.c3b"); _mesh2 = MeshRenderer::create("MeshRendererTest/teapot.c3b"); @@ -1303,15 +1300,12 @@ void FogTestDemo::onEnter() AX_SAFE_RELEASE_NULL(_programState1); AX_SAFE_RELEASE_NULL(_programState2); - auto vertexSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.vert"); - auto fragSource = FileUtils::getInstance()->getStringFromFile("MeshRendererTest/fog.frag"); - auto program = ProgramManager::newProgram(vertexSource, fragSource); + auto program = ProgramManager::getInstance()->loadProgram("custom/fog_vs", "custom/fog_fs"); _programState1 = new backend::ProgramState(program); _programState2 = new backend::ProgramState(program); _mesh1->setProgramState(_programState1); _mesh2->setProgramState(_programState2); - AX_SAFE_RELEASE(program); auto fogColor = Vec4(0.5, 0.5, 0.5, 1.0); float fogStart = 10; diff --git a/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp b/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp index c6a75af04e..0cb84f55cf 100644 --- a/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp +++ b/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp @@ -31,11 +31,8 @@ namespace { -enum CustomProgramType : uint32_t -{ - BLUR = 1, - SEPIA = 2, -}; +static uint64_t s_blur_program_id = 0; +static uint64_t s_sepia_program_id = 0; } USING_NS_AX; @@ -74,14 +71,13 @@ private: NewRendererTests::NewRendererTests() { - auto programManager = ProgramManager::getInstance(); - programManager->registerCustomProgram(CustomProgramType::BLUR, positionTextureColor_vert, - "example_Blur_fs"sv, - VertexLayoutHelper::setupSprite); - programManager->registerCustomProgram( - CustomProgramType::SEPIA, positionTextureColor_vert, - "example_Sepia_fs"sv, - VertexLayoutHelper::setupSprite); + auto programManager = ProgramManager::getInstance(); + s_blur_program_id = programManager->registerCustomProgram(positionTextureColor_vert, + "custom/example_Blur_fs"sv, + VertexLayoutType::Sprite); + s_sepia_program_id = programManager->registerCustomProgram(positionTextureColor_vert, + "custom/example_Sepia_fs"sv, + VertexLayoutType::Sprite); ADD_TEST_CASE(NewSpriteTest); ADD_TEST_CASE(GroupCommandTest); @@ -857,7 +853,7 @@ RendererUniformBatch::RendererUniformBatch() ax::backend::ProgramState* RendererUniformBatch::createBlurProgramState() { auto programState = - new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::BLUR)); + new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id)); programState->autorelease(); backend::UniformLocation loc = programState->getUniformLocation("resolution"); @@ -877,11 +873,7 @@ ax::backend::ProgramState* RendererUniformBatch::createBlurProgramState() ax::backend::ProgramState* RendererUniformBatch::createSepiaProgramState() { - auto programState = - new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::SEPIA)); - - // programState->hashOfUniforms(); - + auto programState = new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id)); programState->autorelease(); return programState; } @@ -931,7 +923,7 @@ RendererUniformBatch2::RendererUniformBatch2() backend::ProgramState* RendererUniformBatch2::createBlurProgramState() { auto programState = - new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::BLUR)); + new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id)); backend::UniformLocation loc = programState->getUniformLocation("resolution"); auto resolution = Vec2(85, 121); @@ -951,7 +943,7 @@ backend::ProgramState* RendererUniformBatch2::createBlurProgramState() backend::ProgramState* RendererUniformBatch2::createSepiaProgramState() { auto programState = - new backend::ProgramState(ProgramManager::getInstance()->getCustomProgram(CustomProgramType::SEPIA)); + new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id)); programState->autorelease(); return programState; } diff --git a/tests/cpp-tests/Source/NodeTest/NodeTest.cpp b/tests/cpp-tests/Source/NodeTest/NodeTest.cpp index d66d48754a..5fd7f0798a 100644 --- a/tests/cpp-tests/Source/NodeTest/NodeTest.cpp +++ b/tests/cpp-tests/Source/NodeTest/NodeTest.cpp @@ -943,19 +943,19 @@ public: sprite->autorelease(); auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); auto programState = new backend::ProgramState(program); - sprite->setProgramState(programState, false); + sprite->setProgramState(programState, true); return sprite; } - bool setProgramState(backend::ProgramState* programState, bool needsRetain = true) override; + bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; protected: CustomCommand _customCommand; }; -bool MySprite::setProgramState(backend::ProgramState* programState, bool needsRetain) +bool MySprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) { - if (Sprite::setProgramState(programState, needsRetain)) + if (Sprite::setProgramState(programState, ownPS)) { auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); pipelineDescriptor.programState = programState; diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp b/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp index cd7ec64540..7fad2fcefb 100644 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp +++ b/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp @@ -88,6 +88,8 @@ ShaderNode* ShaderNode::shaderNodeWithVertex(std::string_view vert, std::string_ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag) { + if (vert.empty()) + vert = position_vert; _vertFileName = vert; _fragFileName = frag; @@ -103,11 +105,13 @@ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag) // init custom command auto attrPosLoc = _programState->getAttributeLocation("a_position"); - _programState->setVertexAttrib("a_position", attrPosLoc, backend::VertexFormat::FLOAT2, 0, false); + + auto vertexLayout = _programState->getMutableVertexLayout(); + vertexLayout->setAttrib("a_position", attrPosLoc, backend::VertexFormat::FLOAT2, 0, false); float w = SIZE_X, h = SIZE_Y; Vec2 vertices[6] = {Vec2(0.0f, 0.0f), Vec2(w, 0.0f), Vec2(w, h), Vec2(0.0f, 0.0f), Vec2(0.0f, h), Vec2(w, h)}; - _programState->setVertexStride(sizeof(Vec2)); + vertexLayout->setStride(sizeof(Vec2)); /* * TODO: the Y-coordinate of subclasses are flipped in metal @@ -125,28 +129,10 @@ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag) void ShaderNode::loadShaderVertex(std::string_view vert, std::string_view frag) { - auto fileUtiles = FileUtils::getInstance(); - - // frag - auto fragmentFilePath = fileUtiles->fullPathForFilename(frag); - auto fragSource = fileUtiles->getStringFromFile(fragmentFilePath); - - // vert - std::string vertSource; - if (vert.empty()) - { - vertSource = position_vert; - } - else - { - std::string vertexFilePath = fileUtiles->fullPathForFilename(vert); - vertSource = fileUtiles->getStringFromFile(vertexFilePath); - } - auto program = ProgramManager::newProgram(vertSource, fragSource, VertexLayoutHelper::setupSprite); + auto program = ProgramManager::getInstance()->loadProgram(vert, frag, VertexLayoutType::Sprite); auto programState = new backend::ProgramState(program); setProgramState(programState); AX_SAFE_RELEASE(programState); - AX_SAFE_RELEASE(program); } void ShaderNode::update(float dt) @@ -217,7 +203,7 @@ bool ShaderMonjori::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Monjori.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Monjori_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -247,7 +233,7 @@ bool ShaderMandelbrot::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Mandelbrot.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Mandelbrot_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -276,7 +262,7 @@ bool ShaderJulia::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Julia.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Julia_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -305,7 +291,7 @@ bool ShaderHeart::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Heart.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Heart_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -335,7 +321,7 @@ bool ShaderFlower::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Flower.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Flower_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -365,7 +351,7 @@ bool ShaderPlasma::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/example_Plasma.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/example_Plasma_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -448,14 +434,10 @@ bool SpriteBlur::initWithTexture(Texture2D* texture, const Rect& rect) void SpriteBlur::initProgram() { - std::string fragSource = FileUtils::getInstance()->getStringFromFile( - FileUtils::getInstance()->fullPathForFilename("Shaders/example_Blur.fsh")); - - auto program = ProgramManager::newProgram(positionTextureColor_vert, fragSource, VertexLayoutHelper::setupSprite); + auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_Blur_fs", VertexLayoutType::Sprite); auto programState = new backend::ProgramState(program); setProgramState(programState); AX_SAFE_RELEASE(programState); - AX_SAFE_RELEASE(program); auto size = getTexture()->getContentSizeInPixels(); @@ -581,10 +563,10 @@ bool ShaderRetroEffect::init() { auto fragStr = FileUtils::getInstance()->getStringFromFile( - FileUtils::getInstance()->fullPathForFilename("Shaders/example_HorizontalColor.fsh")); + FileUtils::getInstance()->fullPathForFilename("custom/example_HorizontalColor_fs")); char* fragSource = (char*)fragStr.c_str(); - auto program = ProgramManager::newProgram(positionTextureColor_vert, fragSource, VertexLayoutHelper::setupSprite); + auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_HorizontalColor_fs", VertexLayoutType::Sprite); auto p = new backend::ProgramState(program); auto director = Director::getInstance(); const auto& screenSizeLocation = p->getUniformLocation("u_screenSize"); @@ -605,7 +587,6 @@ bool ShaderRetroEffect::init() addChild(_label); scheduleUpdate(); - AX_SAFE_RELEASE(program); return true; } @@ -658,7 +639,7 @@ bool ShaderLensFlare::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/shadertoy_LensFlare.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/shadertoy_LensFlare_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -690,7 +671,7 @@ bool ShaderGlow::init() { if (ShaderTestDemo::init()) { - auto sn = ShaderNode::shaderNodeWithVertex("", "Shaders/shadertoy_Glow.fsh"); + auto sn = ShaderNode::shaderNodeWithVertex("", "custom/shadertoy_Glow_fs"); auto s = Director::getInstance()->getWinSize(); sn->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -764,10 +745,7 @@ bool ShaderMultiTexture::init() addChild(_sprite); _sprite->setPosition(Vec2(s.width / 2, s.height / 2)); - auto* fu = FileUtils::getInstance(); - auto vertexShader = fu->getStringFromFile("Shaders/example_MultiTexture.vsh"); - auto fragmentShader = fu->getStringFromFile("Shaders/example_MultiTexture.fsh"); - auto program = ProgramManager::newProgram(vertexShader, fragmentShader, VertexLayoutHelper::setupSprite); + auto program = ProgramManager::getInstance()->loadProgram("custom/example_MultiTexture_vs", "custom/example_MultiTexture_fs", VertexLayoutType::Sprite); auto programState = new backend::ProgramState(program); _sprite->setProgramState(programState); @@ -785,7 +763,6 @@ bool ShaderMultiTexture::init() menu->setPosition(s.width * 7 / 8, s.height / 2); AX_SAFE_RELEASE(programState); - AX_SAFE_RELEASE(program); return true; } diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest.h b/tests/cpp-tests/Source/ShaderTest/ShaderTest.h index 29a22eed45..9c05d0c3e3 100644 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest.h +++ b/tests/cpp-tests/Source/ShaderTest/ShaderTest.h @@ -153,9 +153,9 @@ protected: bool initWithVertex(std::string_view vert, std::string_view frag); void loadShaderVertex(std::string_view vert, std::string_view frag); - virtual bool setProgramState(ax::backend::ProgramState* programState, bool needsRetain = true) override + virtual bool setProgramState(ax::backend::ProgramState* programState, bool ownPS = false) override { - if (Node::setProgramState(programState, needsRetain)) + if (Node::setProgramState(programState, ownPS)) { _customCommand.getPipelineDescriptor().programState = programState; updateUniforms(); diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest.vsh.h b/tests/cpp-tests/Source/ShaderTest/ShaderTest.vsh.h deleted file mode 100644 index 8245ba9f4c..0000000000 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest.vsh.h +++ /dev/null @@ -1,32 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - https://axmolengine.github.io/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#define STRINGIFY(A) #A -static const char* shadertestvsh = STRINGIFY( - - attribute vec4 a_position; - - void main() { gl_Position = AX_MVPMatrix * a_position; } - -); diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp b/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp index 56dfa18f3f..03545cef47 100644 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp +++ b/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp @@ -183,17 +183,9 @@ protected: bool Effect::initProgramState(std::string_view fragmentFilename) { - auto fileUtiles = FileUtils::getInstance(); - auto fragmentFullPath = fileUtiles->fullPathForFilename(fragmentFilename); - auto fragSource = fileUtiles->getStringFromFile(fragmentFullPath); - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) - _fragSource = fragSource; -#endif - auto program = ProgramManager::newProgram(positionTextureColor_vert, fragSource, VertexLayoutHelper::setupSprite); + auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, fragmentFilename, VertexLayoutType::Sprite); auto programState = new backend::ProgramState(program); AX_SAFE_RELEASE(_programState); - AX_SAFE_RELEASE(program); _programState = programState; return _programState != nullptr; @@ -235,7 +227,7 @@ void EffectBlur::setTarget(EffectSprite* sprite) bool EffectBlur::init(float blurRadius, float sampleNum) { - initProgramState("Shaders/example_Blur.fsh"); + initProgramState("custom/example_Blur_fs"); _blurRadius = blurRadius; _blurSampleNum = sampleNum; @@ -260,7 +252,7 @@ public: bool init() { - initProgramState("Shaders/example_Outline.fsh"); + initProgramState("custom/example_Outline_fs"); Vec3 color(1.0f, 0.2f, 0.3f); float radius = 0.01f; @@ -282,7 +274,7 @@ public: protected: bool init() { - initProgramState("Shaders/example_Noisy.fsh"); + initProgramState("custom/example_Noisy_fs"); return true; } @@ -302,7 +294,7 @@ public: protected: bool init() { - initProgramState("Shaders/example_EdgeDetection.fsh"); + initProgramState("custom/example_EdgeDetection_fs"); return true; } @@ -322,7 +314,7 @@ public: protected: bool init() { - initProgramState("Shaders/example_GreyScale.fsh"); + initProgramState("custom/example_GreyScale_fs"); return true; } }; @@ -336,7 +328,7 @@ public: protected: bool init() { - initProgramState("Shaders/example_Sepia.fsh"); + initProgramState("custom/example_Sepia_fs"); return true; } }; @@ -350,7 +342,7 @@ public: protected: bool init() { - initProgramState("Shaders/example_Bloom.fsh"); + initProgramState("custom/example_Bloom_fs"); return true; } @@ -370,7 +362,7 @@ public: protected: bool init() { - initProgramState("Shaders/example_CelShading.fsh"); + initProgramState("custom/example_CelShading_fs"); return true; } @@ -390,7 +382,7 @@ public: protected: bool init() { - initProgramState("Shaders/example_LensFlare.fsh"); + initProgramState("custom/example_LensFlare_fs"); return true; } @@ -436,7 +428,7 @@ protected: bool EffectNormalMapped::init() { - initProgramState("Shaders3D/Normal.frag"); + initProgramState("custom/Normal_fs"); _kBump = 2; return true; } diff --git a/tests/cpp-tests/Source/ShaderTest/shaderTest.psh.h b/tests/cpp-tests/Source/ShaderTest/shaderTest.psh.h deleted file mode 100644 index 51442f2c85..0000000000 --- a/tests/cpp-tests/Source/ShaderTest/shaderTest.psh.h +++ /dev/null @@ -1,437 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - - https://axmolengine.github.io/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#define STRINGIFY(A) #A - -static const char* starFlame = STRINGIFY( - - uniform vec2 center; uniform vec2 resolution; - - vec2 iResolution = resolution; // viewport resolution (in pixels) - float iGlobalTime = AX_Time[1]; // shader playback time (in seconds) - // uniform float iChannelTime[4]; // channel playback time (in seconds) - // uniform vec3 iChannelResolution[4]; // channel resolution (in pixels) - vec4 iMouse = vec4(0, 0, 0, 0); // mouse pixel coords. xy: current (if MLB down), zw: click - // uniform sampler2D iChannel0; // input channel. XX = 2D/Cube - - float noise(vec3 p) // Thx to Las^Mercury - { - vec3 i = floor(p); - vec4 a = dot(i, vec3(1., 57., 21.)) + vec4(0., 57., 21., 78.); - vec3 f = cos((p - i) * acos(-1.)) * (-.5) + .5; - a = mix(sin(cos(a) * a), sin(cos(1. + a) * (1. + a)), f.x); - a.xy = mix(a.xz, a.yw, f.y); - return mix(a.x, a.y, f.z); - } - - float sphere(vec3 p, vec4 spr) { return length(spr.xyz - p) - spr.w; } - - float flame(vec3 p) { - float d = sphere(p * vec3(1., .5, 1.), vec4(.0, -1., .0, 1.)); - return d + (noise(p + vec3(.0, iGlobalTime * 2., .0)) + noise(p * 3.) * .5) * .25 * (p.y); - } - - float scene(vec3 p) { return min(100. - length(p), abs(flame(p))); } - - vec4 raymarch(vec3 org, vec3 dir) { - float d = 0.0; - float glow = 0.0; - float eps = 0.02; - vec3 p = org; - bool glowed = false; - - for (int i = 0; i < 64; i++) - { - d = scene(p) + eps; - p += d * dir; - if (d > eps) - { - if (flame(p) < .0) - glowed = true; - if (glowed) - glow = float(i) / 64.; - } - } - return vec4(p, glow); - } - - void main() { - vec2 v = -1.0 + (2.0 * gl_FragCoord.xy) / iResolution.xy; - // vec2 v = 2.0 * gl_FragCoord.xy / iResolution.xy; - v.x *= iResolution.x / iResolution.y; - - vec3 org = vec3(0., -2., 4.); - vec3 dir = normalize(vec3(v.x * 1.6, -v.y, -1.5)); - - vec4 p = raymarch(org, dir); - float glow = p.w; - - vec4 col = mix(vec4(1., .5, .1, 1.), vec4(0.1, .5, 1., 1.), p.y * .02 + .4); - - gl_FragColor = mix(vec4(0.), col, pow(glow * 2., 4.)); - // gl_FragColor = col; - // gl_FragColor = mix(vec4(1.), mix(vec4(1.,.5,.1,1.),vec4(0.1,.5,1.,1.),p.y*.02+.4), pow(glow*2.,4.)); - } - -); - -static const char* starNestFrg = STRINGIFY( - - uniform vec2 center; uniform vec2 resolution; - - vec2 iCenter = center; - vec2 iResolution = resolution; // viewport resolution (in pixels) - float iGlobalTime = AX_Time[1]; // shader playback time (in seconds) - // uniform float iChannelTime[4]; // channel playback time (in seconds) - // uniform vec3 iChannelResolution[4]; // channel resolution (in pixels) - vec4 iMouse = vec4(0, 0, 0, 0); // mouse pixel coords. xy: current (if MLB down), zw: click - // uniform sampler2D iChannel0; // input channel. XX = 2D/Cube - - // Star Nest by Pablo Román Andrioli - - // This content is under the MIT License. - - int iterations = 17; - float formuparam = 0.53; - - int volsteps = 20; - float stepsize = 0.1; - - float zoom = 0.800; - float tile = 0.850; - float speed = 0.010; - - float brightness = 0.0015; - float darkmatter = 0.300; - float distfading = 0.730; - float saturation = 0.850; - - void main() { - // iCenter = vec2(300, 300); - // get coords and direction - vec2 uv = gl_FragCoord.xy / iResolution.xy - .5; - // vec2 uv=gl_FragCoord.xy/iResolution.xy ; - // vec2 uv = ( 2* gl_FragCoord.xy - iCenter.xy) / resolution.xy; - uv.y *= iResolution.y / iResolution.x; - - // vec2 uv = 2.0* (gl_FragCoord.xy-iResolution.xy)/min(iResolution.y,iResolution.x); - - vec3 dir = vec3(uv * zoom, 1.); - float time = iGlobalTime * speed + .25; - - // mouse rotation - float a1 = .5 + iMouse.x / iResolution.x * 2.; - float a2 = .8 + iMouse.y / iResolution.y * 2.; - mat2 rot1 = mat2(cos(a1), sin(a1), -sin(a1), cos(a1)); - mat2 rot2 = mat2(cos(a2), sin(a2), -sin(a2), cos(a2)); - dir.xz *= rot1; - dir.xy *= rot2; - vec3 from = vec3(1., .5, 0.5); - from += vec3(time * 2., time, -2.); - from.xz *= rot1; - from.xy *= rot2; - - // volumetric rendering - float s = 0.1; - float fade = 1.; - vec3 v = vec3(0.); - for (int r = 0; r < volsteps; r++) - { - vec3 p = from + s * dir * .5; - p = abs(vec3(tile) - mod(p, vec3(tile * 2.))); // tiling fold - - float a = 0.; - float pa = 0.; - for (int i = 0; i < iterations; i++) - { - p = abs(p) / dot(p, p) - formuparam; // the magic formula - a += abs(length(p) - pa); // absolute sum of average change - pa = length(p); - } - float dm = max(0., darkmatter - a * a * .001); // dark matter - a *= a * a; // add contrast - if (r > 6) - fade *= 1. - dm; // dark matter, don't render near - // v+=vec3(dm,dm*.5,0.); - v += fade; - v += vec3(s, s * s, s * s * s * s) * a * brightness * fade; // coloring based on distance - fade *= distfading; // distance fading - s += stepsize; - } - v = mix(vec3(length(v)), v, saturation); // color adjust - gl_FragColor = vec4(v * .01, 1.); - }); - -static const char* shadertoyRelentlessFrag = STRINGIFY( - - uniform vec2 center; uniform vec2 resolution; - - vec2 iCenter = center; - vec2 iResolution = resolution; // viewport resolution (in pixels) - float iGlobalTime = AX_Time[1]; // shader playback time (in seconds) - // uniform float iChannelTime[4]; // channel playback time (in seconds) - // uniform vec3 iChannelResolution[4]; // channel resolution (in pixels) - - vec4 iMouse = vec4(0, 0, 0, 0); // mouse pixel coords. xy: current (if MLB down), zw: click - // uniform sampler2D iChannel0; // input channel. XX = 2D/Cube - - // srtuss, 2013 - // collecting some design ideas for a new game project. - // no raymarching is used. - - // if i could add a custom soundtrack, it'd use this one (essential for desired sensation) - // http://www.youtube.com/watch?v=1uFAu65tZpo - - //#define GREEN_VERSION - - // ** improved camera shaking - // ** cleaned up code - // ** added stuff to the gates - - float time = iGlobalTime; - - vec2 rotate(vec2 p, float a) { - return vec2(p.x * cos(a) - p.y * sin(a), p.x * sin(a) + p.y * cos(a)); - } float box(vec2 p, vec2 b, float r) { return length(max(abs(p) - b, 0.0)) - r; } - - // iq's ray-plane-intersection code - vec3 intersect(in vec3 o, in vec3 d, vec3 c, vec3 u, vec3 v) { - vec3 q = o - c; - return vec3(dot(cross(u, v), q), dot(cross(q, u), d), dot(cross(v, q), d)) / dot(cross(v, u), d); - } - - // some noise functions for fast developing - float rand11(float p) { return fract(sin(p * 591.32) * 43758.5357); } - - float rand12(vec2 p) { return fract(sin(dot(p.xy, vec2(12.9898, 78.233))) * 43758.5357); } - - vec2 rand21(float p) { return fract(vec2(sin(p * 591.32), cos(p * 391.32))); } - - vec2 rand22(in vec2 p) { return fract(vec2(sin(p.x * 591.32 + p.y * 154.077), cos(p.x * 391.32 + p.y * 49.077))); } - - float noise11(float p) { - float fl = floor(p); - return mix(rand11(fl), rand11(fl + 1.0), fract(p)); // smoothstep(0.0, 1.0, fract(p))); - } - - float fbm11(float p) { return noise11(p) * 0.5 + noise11(p * 2.0) * 0.25 + noise11(p * 5.0) * 0.125; } - - vec3 noise31(float p) { return vec3(noise11(p), noise11(p + 18.952), noise11(p - 11.372)) * 2.0 - 1.0; } - - // something that looks a bit like godrays coming from the surface - float sky(vec3 p) { - float a = atan(p.x, p.z); - float t = time * 0.1; - float v = - rand11(floor(a * 4.0 + t)) * 0.5 + rand11(floor(a * 8.0 - t)) * 0.25 + rand11(floor(a * 16.0 + t)) * 0.125; - return v; - } - - vec3 voronoi(in vec2 x) { - vec2 n = floor(x); // grid cell id - vec2 f = fract(x); // grid internal position - vec2 mg; // shortest distance... - vec2 mr; // ..and second shortest distance - float md = 8.0; - float md2 = 8.0; - for (int j = -1; j <= 1; j++) - { - for (int i = -1; i <= 1; i++) - { - vec2 g = vec2(float(i), float(j)); // cell id - vec2 o = rand22(n + g); // offset to edge point - vec2 r = g + o - f; - - float d = max(abs(r.x), abs(r.y)); // distance to the edge - - if (d < md) - { - md2 = md; - md = d; - mr = r; - mg = g; - } - else if (d < md2) - { - md2 = d; - } - } - } - return vec3(n + mg, md2 - md); - } - - //#define A2V(a) vec2(sin((a) * 6.28318531 / 100.0), cos((a) * 6.28318531 / 100.0)) - vec2 A2V(float a) { return vec2(sin((a)*6.28318531 / 100.0), cos((a)*6.28318531 / 100.0)); } - - float circles(vec2 p) { - float v; - float w; - float l; - float c; - vec2 pp; - l = length(p); - - pp = rotate(p, time * 3.0); - c = max(dot(pp, normalize(vec2(-0.2, 0.5))), -dot(pp, normalize(vec2(0.2, 0.5)))); - c = min(c, max(dot(pp, normalize(vec2(0.5, -0.5))), -dot(pp, normalize(vec2(0.2, -0.5))))); - c = min(c, max(dot(pp, normalize(vec2(0.3, 0.5))), -dot(pp, normalize(vec2(0.2, 0.5))))); - - // innerest stuff - v = abs(l - 0.5) - 0.03; - v = max(v, -c); - v = min(v, abs(l - 0.54) - 0.02); - v = min(v, abs(l - 0.64) - 0.05); - - pp = rotate(p, time * -1.333); - c = max(dot(pp, A2V(-5.0)), -dot(pp, A2V(5.0))); - c = min(c, max(dot(pp, A2V(25.0 - 5.0)), -dot(pp, A2V(25.0 + 5.0)))); - c = min(c, max(dot(pp, A2V(50.0 - 5.0)), -dot(pp, A2V(50.0 + 5.0)))); - c = min(c, max(dot(pp, A2V(75.0 - 5.0)), -dot(pp, A2V(75.0 + 5.0)))); - - w = abs(l - 0.83) - 0.09; - v = min(v, max(w, c)); - - return v; - } - - float shade1(float d) { - float v = 1.0 - smoothstep(0.0, mix(0.012, 0.2, 0.0), d); - float g = exp(d * -20.0); - return v + g * 0.5; - } - - void main() { - vec2 uv = gl_FragCoord.xy / iResolution.xy; - uv = uv * 2.0 - 1.0; - uv.x *= iResolution.x / iResolution.y; - - // using an iq styled camera this time :) - // ray origin - vec3 ro = 0.7 * vec3(cos(0.2 * time), 0.0, sin(0.2 * time)); - ro.y = cos(0.6 * time) * 0.3 + 0.65; - // camera look at - vec3 ta = vec3(0.0, 0.2, 0.0); - - // camera shake intensity - float shake = clamp(3.0 * (1.0 - length(ro.yz)), 0.3, 1.0); - float st = mod(time, 10.0) * 143.0; - - // build camera matrix - vec3 ww = normalize(ta - ro + noise31(st) * shake * 0.01); - vec3 uu = normalize(cross(ww, normalize(vec3(0.0, 1.0, 0.2 * sin(time))))); - vec3 vv = normalize(cross(uu, ww)); - // obtain ray direction - vec3 rd = normalize(uv.x * uu + uv.y * vv + 1.0 * ww); - - // shaking and movement - ro += noise31(-st) * shake * 0.015; - ro.x += time * 2.0; - - float inten = 0.0; - - // background - float sd = dot(rd, vec3(0.0, 1.0, 0.0)); - inten = pow(1.0 - abs(sd), 20.0) + pow(sky(rd), 5.0) * step(0.0, rd.y) * 0.2; - - vec3 its; - float v; - float g; - - // voronoi floor layers - for (int i = 0; i < 4; i++) - { - float layer = float(i); - its = intersect(ro, rd, vec3(0.0, -5.0 - layer * 5.0, 0.0), vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0)); - if (its.x > 0.0) - { - vec3 vo = voronoi((its.yz) * 0.05 + 8.0 * rand21(float(i))); - v = exp(-100.0 * (vo.z - 0.02)); - - float fx = 0.0; - - // add some special fx to lowest layer - if (i == 3) - { - float crd = 0.0; // fract(time * 0.2) * 50.0 - 25.0; - float fxi = cos(vo.x * 0.2 + time * 1.5); // abs(crd - vo.x); - fx = clamp(smoothstep(0.9, 1.0, fxi), 0.0, 0.9) * 1.0 * rand12(vo.xy); - fx *= exp(-3.0 * vo.z) * 2.0; - } - inten += v * 0.1 + fx; - } - } - - // draw the gates, 4 should be enough - float gatex = floor(ro.x / 8.0 + 0.5) * 8.0 + 4.0; - float go = -16.0; - for (int i = 0; i < 4; i++) - { - its = intersect(ro, rd, vec3(gatex + go, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0)); - if (dot(its.yz, its.yz) < 2.0 && its.x > 0.0) - { - v = circles(its.yz); - inten += shade1(v); - } - - go += 8.0; - } - - // draw the stream - for (int j = 0; j < 20; j++) - { - float id = float(j); - - vec3 bp = vec3(0.0, (rand11(id) * 2.0 - 1.0) * 0.25, 0.0); - vec3 its = intersect(ro, rd, bp, vec3(1.0, 0.0, 0.0), vec3(0.0, 0.0, 1.0)); - - if (its.x > 0.0) - { - vec2 pp = its.yz; - float spd = (1.0 + rand11(id) * 3.0) * 2.5; - pp.y += time * spd; - pp += (rand21(id) * 2.0 - 1.0) * vec2(0.3, 1.0); - float rep = rand11(id) + 1.5; - pp.y = mod(pp.y, rep * 2.0) - rep; - float d = box(pp, vec2(0.02, 0.3), 0.1); - float foc = 0.0; - float v = 1.0 - smoothstep(0.0, 0.03, abs(d) - 0.001); - float g = min(exp(d * -20.0), 2.0); - - inten += (v + g * 0.7) * 0.5; - } - } - - inten *= 0.4 + (sin(time) * 0.5 + 0.5) * 0.6; - - // find a color for the computed intensity -#ifdef GREEN_VERSION - vec3 col = pow(vec3(inten), vec3(2.0, 0.15, 9.0)); -#else - vec3 col = pow(vec3(inten), 1.5 * vec3(0.15, 2.0, 9.0)); -#endif - - gl_FragColor = vec4(col, 1.0); - } - -); diff --git a/tests/cpp-tests/Source/SpineTest/SpineTest.cpp b/tests/cpp-tests/Source/SpineTest/SpineTest.cpp index f87ec48f4a..1b824b4cd2 100644 --- a/tests/cpp-tests/Source/SpineTest/SpineTest.cpp +++ b/tests/cpp-tests/Source/SpineTest/SpineTest.cpp @@ -28,7 +28,6 @@ #include #include #include "spine/spine.h" -#include "renderer/Colorizer.h" USING_NS_AX; using namespace std; @@ -146,7 +145,6 @@ bool SpineTestLayer::init() SET_UNIFORM(skeleton1PS, "resolution", resolution); SET_UNIFORM(skeleton1PS, "blurRadius", blurRadius); SET_UNIFORM(skeleton1PS, "sampleNum", sampleNum); - skeleton1PS->hashOfUniforms(); } } @@ -364,7 +362,11 @@ bool MixAndMatchExample::init() SCALE_SKELETON_NODE(skeletonNode); - Colorizer::enableNodeIntelliShading(skeletonNode, Vec3(92.0f, 1.0f, 1.2f), Vec3::ZERO); + // load hsv as custom, we don't want batch draw + auto hsvProg = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, hsv_frag); + auto ps1 = new backend::ProgramState(hsvProg); + SET_UNIFORM(ps1, "u_hsv", Vec3(92.0f, 1.0f, 1.2f)); + skeletonNode->setProgramState(ps1, true); /* -------- skeletonNode2 with same spine animation file ------------ */ auto skeletonNode2 = SkeletonAnimation::createWithBinaryFile("mix-and-match-pro.skel", "mix-and-match.atlas", 0.5); @@ -392,7 +394,9 @@ bool MixAndMatchExample::init() SCALE_SKELETON_NODE(skeletonNode2); - Colorizer::enableNodeIntelliShading(skeletonNode2, Vec3(45.0f, 1.0f, 1.2f), Vec3::ZERO); + auto ps2 = new backend::ProgramState(hsvProg); + SET_UNIFORM(ps2, "u_hsv", Vec3(-45.0f, 1.0f, 1.2f)); + skeletonNode2->setProgramState(ps2, true); return true; } @@ -516,11 +520,9 @@ bool SpineboyExample::init() skeletonNode->setPosition(Vec2(_contentSize.width / 2, 20)); addChild(skeletonNode); - auto programCache = backend::ProgramCache::getInstance(); - programCache->registerCustomProgram(101, positionTextureColor_vert, - FileUtils::getInstance()->getStringFromFile("Shaders/example_Blur.fsh"), VertexLayoutHelper::setupSprite); - auto program = programCache->getCustomProgram(101); - skeletonNode->setProgramState(new backend::ProgramState(program), false); + auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_Blur_fs", + VertexLayoutType::Sprite); + skeletonNode->setProgramState(new backend::ProgramState(program), true); //auto skeleton1PS = skeletonNode->getProgramState(); diff --git a/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua b/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua index d1e79b54b8..2d813b616b 100644 --- a/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua +++ b/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua @@ -722,13 +722,9 @@ function FogTestDemo:createLayer3D() self:addChild(layer3D,0) self._layer3D = layer3D - local vertexShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/fog.vert") - local fragmentShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/fog.frag") - - local program = ccb.Device:getInstance():newProgram(vertexShader, fragmentShader) + local program = axb.ProgramManager:getInstance():loadProgram('custom/fog_vs', 'custom/fog_fs') self._shader1 = ccb.ProgramState:new(program) self._shader2 = self._shader1:clone() - program:release() self._sprite3D1 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") self._sprite3D2 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") diff --git a/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua b/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua index d406928f91..872f58c0d3 100644 --- a/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua +++ b/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua @@ -312,11 +312,8 @@ function Scene3DTest:create3DWorld() --then, create skybox --create and set our custom shader - local cmVert = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.vert") - local cmFrag = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.frag") - local program = ccb.Device:getInstance():newProgram(cmVert, cmFrag) + local program = axb.ProgramManager:getInstance():loadProgram('custom/cube_map_vs', 'custom/cube_map_fs') local state = ccb.ProgramState:new(program) - program:release() --create the second texture for cylinder self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", "MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg", diff --git a/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua b/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua index f8cb9330d0..7ba3616838 100644 --- a/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua +++ b/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua @@ -1123,11 +1123,8 @@ function Sprite3DCubeMapTest:addNewSpriteWithCoords(pos) --create a teapot self._teapot = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") - local vertexShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.vert") - local fragmentShader = cc.FileUtils:getInstance():getStringFromFile("MeshRendererTest/cube_map.frag") - local program = ccb.Device:getInstance():newProgram(vertexShader, fragmentShader) + local program = axb.ProgramManager:getInstance():loadProgram('custom/cube_map_vs', 'custom/cube_map_fs') local programState = ccb.ProgramState:new(program) - program:release() self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", "MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg", diff --git a/tests/lua-tests/Source/lua_test_bindings.cpp b/tests/lua-tests/Source/lua_test_bindings.cpp index c529c185a5..eeb80bbdfd 100644 --- a/tests/lua-tests/Source/lua_test_bindings.cpp +++ b/tests/lua-tests/Source/lua_test_bindings.cpp @@ -157,16 +157,18 @@ bool DrawNode3D::init() const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); auto iter = attributeInfo.find("a_position"); + auto vertexLayout = _programState->getMutableVertexLayout(); if (iter != attributeInfo.end()) { - _programState->setVertexAttrib(iter->first, iter->second.location, backend::VertexFormat::FLOAT3, 0, false); + vertexLayout->setAttrib(iter->first, iter->second.location, backend::VertexFormat::FLOAT3, 0, false); } iter = attributeInfo.find("a_color"); if (iter != attributeInfo.end()) { - _programState->setVertexAttrib(iter->first, iter->second.location, backend::VertexFormat::UBYTE4, sizeof(Vec3), true); + vertexLayout->setAttrib(iter->first, iter->second.location, backend::VertexFormat::UBYTE4, sizeof(Vec3), + true); } - _programState->setVertexStride(sizeof(V3F_C4B)); + vertexLayout->setStride(sizeof(V3F_C4B)); _customCommand.createVertexBuffer(sizeof(V3F_C4B), INITIAL_VERTEX_BUFFER_LENGTH, CustomCommand::BufferUsage::DYNAMIC);