diff --git a/core/2d/Sprite.cpp b/core/2d/Sprite.cpp index 040f84b3a8..39876590bb 100644 --- a/core/2d/Sprite.cpp +++ b/core/2d/Sprite.cpp @@ -325,23 +325,6 @@ Sprite::~Sprite() * Texture methods */ -/* - * This array is the data of a white image with 2 by 2 dimension. - * It's used for creating a default texture when sprite's texture is set to nullptr. - * Supposing codes as follows: - * - * auto sp = new Sprite(); - * sp->init(); // Texture was set to nullptr, in order to make opacity and color to work correctly, we need to create - * a 2x2 white texture. - * - * The test is in "TestCpp/SpriteTest/Sprite without texture". - */ -static unsigned char cc_2x2_white_image[] = { - // RGBA8888 - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - -#define AX_2x2_WHITE_IMAGE_KEY "/cc_2x2_white_image" - // MARK: texture void Sprite::setTexture(std::string_view filename) { @@ -394,18 +377,7 @@ void Sprite::setTexture(Texture2D* texture) if (texture == nullptr) { // Gets the texture by key firstly. - texture = _director->getTextureCache()->getTextureForKey(AX_2x2_WHITE_IMAGE_KEY); - - // If texture wasn't in cache, create it from RAW data. - if (texture == nullptr) - { - Image* image = new Image(); - bool AX_UNUSED isOK = image->initWithRawData(cc_2x2_white_image, sizeof(cc_2x2_white_image), 2, 2, 8); - AXASSERT(isOK, "The 2x2 empty texture was created unsuccessfully."); - - texture = _director->getTextureCache()->addImage(image, AX_2x2_WHITE_IMAGE_KEY); - AX_SAFE_RELEASE(image); - } + texture = _director->getTextureCache()->getWhiteTexture(); } bool needsUpdatePS = diff --git a/core/3d/Mesh.cpp b/core/3d/Mesh.cpp index 83da33905d..7be9174c9b 100644 --- a/core/3d/Mesh.cpp +++ b/core/3d/Mesh.cpp @@ -90,25 +90,6 @@ void Mesh::resetLightUniformValues() _spotLightUniformRangeInverseValues.assign(maxSpotLight, 0.0f); } -// Generate a dummy texture when the texture file is missing -static Texture2D* getDummyTexture() -{ - auto texture = Director::getInstance()->getTextureCache()->getTextureForKey("/dummyTexture"); - if (!texture) - { -#ifdef NDEBUG - unsigned char data[] = {0, 0, 0, 0}; // 1*1 transparent picture -#else - unsigned char data[] = {255, 0, 0, 255}; // 1*1 red picture -#endif - Image* image = new Image(); - image->initWithRawData(data, sizeof(data), 1, 1, sizeof(unsigned char)); - texture = Director::getInstance()->getTextureCache()->addImage(image, "/dummyTexture"); - image->release(); - } - return texture; -} - Mesh::Mesh() : _skin(nullptr) , _visible(true) @@ -282,7 +263,7 @@ void Mesh::setTexture(Texture2D* tex, NTextureData::Usage usage, bool cacheFileN // it doesn't matter if the material is already set or not // This functionality is added for compatibility issues if (tex == nullptr) - tex = getDummyTexture(); + tex = Director::getInstance()->getTextureCache()->getDummyTexture(); AX_SAFE_RETAIN(tex); AX_SAFE_RELEASE(_textures[usage]); diff --git a/core/renderer/Pass.h b/core/renderer/Pass.h index 0e3f165618..700c7324c0 100644 --- a/core/renderer/Pass.h +++ b/core/renderer/Pass.h @@ -108,7 +108,7 @@ public: void updateMVPUniform(const Mat4& modelView); void setUniformTexture(uint32_t slot, backend::TextureBackend*); // u_tex0 - void setUniformNormTexture(uint32_t slot, backend::TextureBackend*); // u_tex0 + void setUniformNormTexture(uint32_t slot, backend::TextureBackend*); // u_normalTex void setUniformColor(const void*, size_t); // ucolor void setUniformMatrixPalette(const void*, size_t); // u_matrixPalette diff --git a/core/renderer/TextureCache.cpp b/core/renderer/TextureCache.cpp index 01e4f7b770..2c7a9e8966 100644 --- a/core/renderer/TextureCache.cpp +++ b/core/renderer/TextureCache.cpp @@ -384,6 +384,42 @@ void TextureCache::addImageAsyncCallBack(float /*dt*/) } } +Texture2D* TextureCache::getWhiteTexture() +{ + constexpr std::string_view key = "/white-texture"sv; + // Gets the texture by key firstly. + auto texture = this->getTextureForKey(key); + if (texture) return texture; + + // If texture wasn't in cache, create it from RAW data. + unsigned char texls[] = { + // RGBA8888 + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + Image image; + bool AX_UNUSED isOK = image.initWithRawData(texls, sizeof(texls), 2, 2, 8); + AXASSERT(isOK, "The 2x2 empty texture was created unsuccessfully."); + + return this->addImage(&image, key); +} + +Texture2D* TextureCache::getDummyTexture() +{ + constexpr std::string_view key = "/dummy-texture"sv; + // Gets the texture by key firstly. + auto texture = this->getTextureForKey(key); + if (texture) return texture; + + // If texture wasn't in cache, create it from RAW data. +#ifdef NDEBUG + unsigned char texls[] = {0, 0, 0, 0}; // 1*1 transparent picture +#else + unsigned char texls[] = {255, 0, 0, 255}; // 1*1 red picture +#endif + Image image; + bool AX_UNUSED isOK = image.initWithRawData(texls, sizeof(texls), 1, 1, sizeof(unsigned char)); + return this->addImage(&image, key); +} + Texture2D* TextureCache::addImage(std::string_view path) { return addImage(path, Texture2D::getDefaultAlphaPixelFormat()); diff --git a/core/renderer/TextureCache.h b/core/renderer/TextureCache.h index db30098d37..d8659b4eb9 100644 --- a/core/renderer/TextureCache.h +++ b/core/renderer/TextureCache.h @@ -84,6 +84,12 @@ public: * @lua NA */ virtual std::string getDescription() const; + + /** Gets a 2x2 white texture */ + Texture2D* getWhiteTexture(); + + /** Gets 1x1 dummy texture with alpha=0 */ + Texture2D* getDummyTexture(); // Dictionary* snapshotTextures(); diff --git a/core/renderer/backend/Enums.h b/core/renderer/backend/Enums.h index b99edac926..a7af57d612 100644 --- a/core/renderer/backend/Enums.h +++ b/core/renderer/backend/Enums.h @@ -52,11 +52,11 @@ enum class BufferType : uint32_t UNIFORM = UNIFORM_BUFFER }; -enum class ShaderStage : uint32_t +enum class ShaderStage { + UNKNOWN = -1, VERTEX, - FRAGMENT, - VERTEX_AND_FRAGMENT + FRAGMENT }; enum class VertexFormat : uint32_t diff --git a/core/renderer/backend/ProgramState.cpp b/core/renderer/backend/ProgramState.cpp index 26b5027751..83f8cc6640 100644 --- a/core/renderer/backend/ProgramState.cpp +++ b/core/renderer/backend/ProgramState.cpp @@ -236,14 +236,9 @@ void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, c setVertexUniform(uniformLocation.location[0], data, size, uniformLocation.location[1]); break; case backend::ShaderStage::FRAGMENT: - setFragmentUniform(uniformLocation.location[1], data, size); - break; - case backend::ShaderStage::VERTEX_AND_FRAGMENT: - setVertexUniform(uniformLocation.location[0], data, size, uniformLocation.location[1]); - setFragmentUniform(uniformLocation.location[1], data, size); - break; - default: + setFragmentUniform(uniformLocation.location[0], data, size, uniformLocation.location[1]); break; + default:; } } @@ -256,14 +251,13 @@ void ProgramState::setVertexUniform(int location, const void* data, std::size_t memcpy(_vertexUniformBuffer + location + offset, data, size); } -void ProgramState::setFragmentUniform(int location, const void* data, std::size_t size) +void ProgramState::setFragmentUniform(int location, const void* data, std::size_t size, std::size_t offset) { if (location < 0) return; -// float3 etc in Metal has both sizeof and alignment same as float4, need convert to correct laytout #ifdef AX_USE_METAL - memcpy(_fragmentUniformBuffer + location, data, size); + memcpy(_fragmentUniformBuffer + location + offset, data, size); #else assert(false); #endif @@ -345,14 +339,9 @@ void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, setTexture(uniformLocation.location[0], slot, index, texture, _vertexTextureInfos); break; case backend::ShaderStage::FRAGMENT: - setTexture(uniformLocation.location[1], slot, index, texture, _fragmentTextureInfos); - break; - case backend::ShaderStage::VERTEX_AND_FRAGMENT: - setTexture(uniformLocation.location[0], slot, index, texture, _vertexTextureInfos); - setTexture(uniformLocation.location[1], slot, index, texture, _fragmentTextureInfos); - break; - default: + setTexture(uniformLocation.location[0], slot, index, texture, _fragmentTextureInfos); break; + default:; } } @@ -366,14 +355,9 @@ void ProgramState::setTextureArray(const backend::UniformLocation& uniformLocati setTextureArray(uniformLocation.location[0], std::move(slots), std::move(textures), _vertexTextureInfos); break; case backend::ShaderStage::FRAGMENT: - setTextureArray(uniformLocation.location[1], std::move(slots), std::move(textures), _fragmentTextureInfos); - break; - case backend::ShaderStage::VERTEX_AND_FRAGMENT: - setTextureArray(uniformLocation.location[0], std::move(slots), std::move(textures), _vertexTextureInfos); - setTextureArray(uniformLocation.location[1], std::move(slots), std::move(textures), _fragmentTextureInfos); - break; - default: + setTextureArray(uniformLocation.location[0], std::move(slots), std::move(textures), _fragmentTextureInfos); break; + default:; } } diff --git a/core/renderer/backend/ProgramState.h b/core/renderer/backend/ProgramState.h index ad7d5040c8..66fb0ebfdc 100644 --- a/core/renderer/backend/ProgramState.h +++ b/core/renderer/backend/ProgramState.h @@ -342,7 +342,7 @@ protected: * @param data Specifies the new values to be used for the specified uniform variable. * @param size Specifies the uniform data size. */ - void setFragmentUniform(int location, const void* data, std::size_t size); + void setFragmentUniform(int location, const void* data, std::size_t size, std::size_t offset); /** * Set texture. diff --git a/core/renderer/backend/Types.h b/core/renderer/backend/Types.h index 0c94448b01..408d9098cc 100644 --- a/core/renderer/backend/Types.h +++ b/core/renderer/backend/Types.h @@ -81,24 +81,22 @@ struct UniformLocation UniformLocation() { location[0] = -1; location[1] = -1; + shaderStage = ShaderStage::UNKNOWN; } - UniformLocation(int loc, int offset) + UniformLocation(int loc, int offset, ShaderStage stage = ShaderStage::VERTEX) { location[0] = loc; location[1] = offset; + shaderStage = stage; } /** - * in metal, those two locations represent to vertex and fragment location. - * in opengl, location[0] represent the location, and location[1] represent location offset in uniform block. + * both opengl and metal, location[0] represent the location, and location[1] represent location offset in uniform block. */ int location[2]; - ShaderStage shaderStage = ShaderStage::VERTEX; + ShaderStage shaderStage; operator bool() { - if (shaderStage == ShaderStage::VERTEX_AND_FRAGMENT) - return location[0] >= 0 && location[1] >= 0; - else - return location[int(shaderStage)] >= 0; + return shaderStage != ShaderStage::UNKNOWN; } void reset() { location[0] = location[1] = -1; } bool operator==(const UniformLocation& other) const; diff --git a/core/renderer/backend/metal/ProgramMTL.mm b/core/renderer/backend/metal/ProgramMTL.mm index d2b8b95d20..45a11bf82e 100644 --- a/core/renderer/backend/metal/ProgramMTL.mm +++ b/core/renderer/backend/metal/ProgramMTL.mm @@ -62,49 +62,19 @@ int ProgramMTL::getAttributeLocation(std::string_view name) const UniformLocation ProgramMTL::getUniformLocation(backend::Uniform name) const { UniformLocation uniformLocation; - auto vsLocation = _vertexShader->getUniformLocation(name); - auto fsLocation = _fragmentShader->getUniformLocation(name); - if (vsLocation != -1 && fsLocation != -1) - { - uniformLocation.shaderStage = ShaderStage::VERTEX_AND_FRAGMENT; - uniformLocation.location[0] = vsLocation; - uniformLocation.location[1] = fsLocation; - } - else if (vsLocation != -1) - { - uniformLocation.shaderStage = ShaderStage::VERTEX; - uniformLocation.location[0] = vsLocation; - } - else - { - uniformLocation.shaderStage = ShaderStage::FRAGMENT; - uniformLocation.location[1] = fsLocation; - } - return uniformLocation; + uniformLocation = _vertexShader->getUniformLocation(name); + if (uniformLocation.location[0] != -1) + return uniformLocation; + return _fragmentShader->getUniformLocation(name); } UniformLocation ProgramMTL::getUniformLocation(std::string_view uniform) const { UniformLocation uniformLocation; - auto vsLocation = _vertexShader->getUniformLocation(uniform); - auto fsLocation = _fragmentShader->getUniformLocation(uniform); - if (vsLocation != -1 && fsLocation != -1) - { - uniformLocation.shaderStage = ShaderStage::VERTEX_AND_FRAGMENT; - uniformLocation.location[0] = vsLocation; - uniformLocation.location[1] = fsLocation; - } - else if (vsLocation != -1) - { - uniformLocation.shaderStage = ShaderStage::VERTEX; - uniformLocation.location[0] = vsLocation; - } - else - { - uniformLocation.shaderStage = ShaderStage::FRAGMENT; - uniformLocation.location[1] = fsLocation; - } - return uniformLocation; + uniformLocation = _vertexShader->getUniformLocation(uniform); + if (uniformLocation.location[0] != -1) + return uniformLocation; + return _fragmentShader->getUniformLocation(uniform); } int ProgramMTL::getMaxVertexLocation() const diff --git a/core/renderer/backend/metal/ShaderModuleMTL.h b/core/renderer/backend/metal/ShaderModuleMTL.h index ddc17ba981..d561b89fc4 100644 --- a/core/renderer/backend/metal/ShaderModuleMTL.h +++ b/core/renderer/backend/metal/ShaderModuleMTL.h @@ -84,14 +84,14 @@ public: * @param name Specifies the engine built-in uniform enum name. * @return The uniform location. */ - int getUniformLocation(Uniform name) const; + UniformLocation getUniformLocation(Uniform name) const; /** * Get uniform location by name. * @param uniform Specifies the uniform name. * @return The uniform location. */ - int getUniformLocation(std::string_view name) const; + UniformLocation getUniformLocation(std::string_view name) const; /** * Get attribute location by engine built-in attribute enum name. @@ -117,17 +117,18 @@ private: void parseAttibute(SLCReflectContext* context); void parseUniform(SLCReflectContext* context); void parseTexture(SLCReflectContext* context); - void setBuiltinUniformLocation(); - void setBuiltinAttributeLocation(); + void setBuiltinLocations(); id _mtlFunction = nil; hlookup::string_map _activeUniformInfos; hlookup::string_map _attributeInfo; - - int _maxLocation = -1; - int _uniformLocation[UNIFORM_MAX]; + int _attributeLocation[ATTRIBUTE_MAX]; + + int _maxLocation = -1; + UniformLocation _uniformLocation[UNIFORM_MAX]; // the builtin uniform locations + std::size_t _uniformBufferSize = 0; }; diff --git a/core/renderer/backend/metal/ShaderModuleMTL.mm b/core/renderer/backend/metal/ShaderModuleMTL.mm index 89acc16bd2..7be1b97b2b 100644 --- a/core/renderer/backend/metal/ShaderModuleMTL.mm +++ b/core/renderer/backend/metal/ShaderModuleMTL.mm @@ -179,8 +179,7 @@ ShaderModuleMTL::ShaderModuleMTL(id mtlDevice, ShaderStage stage, std assert(false); } - setBuiltinUniformLocation(); - setBuiltinAttributeLocation(); + setBuiltinLocations(); [library release]; } @@ -230,11 +229,11 @@ void ShaderModuleMTL::parseUniform(SLCReflectContext* context) auto array_size = ibs->read(); uniform.count = array_size; - uniform.location = i; + uniform.location = ub_binding; uniform.size = size_bytes; uniform.bufferOffset = offset; uniform.type = format; - _activeUniformInfos[name] = uniform; + _activeUniformInfos[name] = uniform; if (_maxLocation < i) _maxLocation = (i + 1); @@ -256,71 +255,63 @@ void ShaderModuleMTL::parseTexture(SLCReflectContext* context) ibs->advance(sizeof(sgs_refl_texture) - offsetof(sgs_refl_texture, image_dim)); UniformInfo uniform; - uniform.location = binding; + uniform.location = binding; + uniform.bufferOffset = -1; _activeUniformInfos[name] = uniform; } } -int ShaderModuleMTL::getUniformLocation(Uniform name) const +UniformLocation ShaderModuleMTL::getUniformLocation(Uniform name) const { return _uniformLocation[name]; } -int ShaderModuleMTL::getUniformLocation(std::string_view name) const +UniformLocation ShaderModuleMTL::getUniformLocation(std::string_view name) const { auto iter = _activeUniformInfos.find(name); if (iter != _activeUniformInfos.end()) { - return iter->second.location; + return UniformLocation{static_cast(iter->second.location), + static_cast(iter->second.bufferOffset), _stage}; } - else - return -1; + return UniformLocation{}; } -void ShaderModuleMTL::setBuiltinUniformLocation() +void ShaderModuleMTL::setBuiltinLocations() { - std::fill(_uniformLocation, _uniformLocation + UNIFORM_MAX, -1); - /// u_mvpMatrix - auto iter = _activeUniformInfos.find(UNIFORM_NAME_MVP_MATRIX); - if (iter != _activeUniformInfos.end()) - { - _uniformLocation[Uniform::MVP_MATRIX] = iter->second.location; - } + /*--- Builtin Attribs ---*/ - /// u_textColor - iter = _activeUniformInfos.find(UNIFORM_NAME_TEXT_COLOR); - if (iter != _activeUniformInfos.end()) - { - _uniformLocation[Uniform::TEXT_COLOR] = iter->second.location; - } + /// a_position + _attributeLocation[Attribute::POSITION] = getAttributeLocation(ATTRIBUTE_NAME_POSITION); - /// u_effectColor - iter = _activeUniformInfos.find(UNIFORM_NAME_EFFECT_COLOR); - if (iter != _activeUniformInfos.end()) - { - _uniformLocation[Uniform::EFFECT_COLOR] = iter->second.location; - } + /// a_color + _attributeLocation[Attribute::COLOR] = getAttributeLocation(ATTRIBUTE_NAME_COLOR); - /// u_effectType - iter = _activeUniformInfos.find(UNIFORM_NAME_EFFECT_TYPE); - if (iter != _activeUniformInfos.end()) - { - _uniformLocation[Uniform::EFFECT_TYPE] = iter->second.location; - } + /// a_texCoord + _attributeLocation[Attribute::TEXCOORD] = getAttributeLocation(ATTRIBUTE_NAME_TEXCOORD); + + // a_normal + _attributeLocation[Attribute::NORMAL] = getAttributeLocation(ATTRIBUTE_NAME_NORMAL); + + /*--- Builtin Uniforms ---*/ + + /// u_MVPMatrix + _uniformLocation[Uniform::MVP_MATRIX] = getUniformLocation(UNIFORM_NAME_MVP_MATRIX); /// u_tex0 - iter = _activeUniformInfos.find(UNIFORM_NAME_TEXTURE); - if (iter != _activeUniformInfos.end()) - { - _uniformLocation[Uniform::TEXTURE] = iter->second.location; - } + _uniformLocation[Uniform::TEXTURE] = getUniformLocation(UNIFORM_NAME_TEXTURE); /// u_tex1 - iter = _activeUniformInfos.find(UNIFORM_NAME_TEXTURE1); - if (iter != _activeUniformInfos.end()) - { - _uniformLocation[Uniform::TEXTURE1] = iter->second.location; - } + _uniformLocation[Uniform::TEXTURE1] = getUniformLocation(UNIFORM_NAME_TEXTURE1); + + /// u_textColor + _uniformLocation[Uniform::TEXT_COLOR] = getUniformLocation(UNIFORM_NAME_TEXT_COLOR); + + /// u_effectColor + _uniformLocation[Uniform::EFFECT_COLOR] = getUniformLocation(UNIFORM_NAME_EFFECT_COLOR); + + /// u_effectType + _uniformLocation[Uniform::EFFECT_TYPE] = getUniformLocation(UNIFORM_NAME_EFFECT_TYPE); } int ShaderModuleMTL::getAttributeLocation(Attribute name) const @@ -337,36 +328,4 @@ int ShaderModuleMTL::getAttributeLocation(std::string_view name) return -1; } -void ShaderModuleMTL::setBuiltinAttributeLocation() -{ - std::fill(_attributeLocation, _attributeLocation + ATTRIBUTE_MAX, -1); - /// a_position - auto iter = _attributeInfo.find(ATTRIBUTE_NAME_POSITION); - if (iter != _attributeInfo.end()) - { - _attributeLocation[Attribute::POSITION] = iter->second.location; - } - - /// a_color - iter = _attributeInfo.find(ATTRIBUTE_NAME_COLOR); - if (iter != _attributeInfo.end()) - { - _attributeLocation[Attribute::COLOR] = iter->second.location; - } - - /// a_texCoord - iter = _attributeInfo.find(ATTRIBUTE_NAME_TEXCOORD); - if (iter != _attributeInfo.end()) - { - _attributeLocation[Attribute::TEXCOORD] = iter->second.location; - } - - /// a_normal - iter = _attributeInfo.find(ATTRIBUTE_NAME_NORMAL); - if (iter != _attributeInfo.end()) - { - _attributeLocation[Attribute::NORMAL] = iter->second.location; - } -} - NS_AX_BACKEND_END diff --git a/core/renderer/shaders/colorNormalTexture.frag b/core/renderer/shaders/colorNormalTexture.frag index 89d51387ca..65cbe8f43c 100644 --- a/core/renderer/shaders/colorNormalTexture.frag +++ b/core/renderer/shaders/colorNormalTexture.frag @@ -19,11 +19,11 @@ layout(location = SPOTLIGHT_NORM) in vec3 v_spotLightDirection[MAX_SPOT_LIGHT_NU layout(location = NORMAL) in vec3 v_normal; #endif -#ifdef USE_NORMAL_MAPPING -layout(binding = 0) uniform sampler2D u_normalTex; -#endif +layout(binding = 0) uniform sampler2D u_tex0; -layout(binding = 1) uniform sampler2D u_tex0; +#ifdef USE_NORMAL_MAPPING +layout(binding = 1) uniform sampler2D u_normalTex; +#endif layout(std140) uniform fs_ub { vec3 u_DirLightSourceColor[MAX_DIRECTIONAL_LIGHT_NUM]; diff --git a/tests/cpp-tests/Source/shaders/cylinder.vert b/tests/cpp-tests/Source/shaders/cylinder.vert index 70bdbb4099..2361f58cc0 100644 --- a/tests/cpp-tests/Source/shaders/cylinder.vert +++ b/tests/cpp-tests/Source/shaders/cylinder.vert @@ -4,7 +4,6 @@ layout(location = TEXCOORD0) in vec2 a_texCoord; layout(location = TEXCOORD0) out vec2 v_texCoord; layout(std140, binding = 0) uniform vs_ub { - float offset; mat4 u_MVPMatrix; };