diff --git a/cocos/3d/CCMesh.cpp b/cocos/3d/CCMesh.cpp index 30688d27bd..939cd2d15f 100644 --- a/cocos/3d/CCMesh.cpp +++ b/cocos/3d/CCMesh.cpp @@ -283,6 +283,9 @@ void Mesh::setTexture(Texture2D* tex) auto technique = _material->_currentTechnique; for(auto& pass: technique->_passes) { + // FIXME: Ideally it should use glProgramState->setUniformTexture() + // and set CC_Texture0 that way. But trying to it, will trigger + // another bug pass->setTexture(tex); } } diff --git a/cocos/3d/CCSprite3D.cpp b/cocos/3d/CCSprite3D.cpp index f231591cd4..e0afe20449 100644 --- a/cocos/3d/CCSprite3D.cpp +++ b/cocos/3d/CCSprite3D.cpp @@ -606,8 +606,8 @@ void Sprite3D::setTexture(const std::string& texFile) void Sprite3D::setTexture(Texture2D* texture) { - for (auto& state : _meshes) { - state->setTexture(texture); + for (auto mesh: _meshes) { + mesh->setTexture(texture); } } AttachNode* Sprite3D::getAttachNode(const std::string& boneName) diff --git a/cocos/renderer/CCGLProgramState.cpp b/cocos/renderer/CCGLProgramState.cpp index 470704caca..616e5b2d92 100644 --- a/cocos/renderer/CCGLProgramState.cpp +++ b/cocos/renderer/CCGLProgramState.cpp @@ -359,7 +359,7 @@ GLProgramState* GLProgramState::getOrCreateWithShaders(const std::string& vertex GLProgramState::GLProgramState() : _uniformAttributeValueDirty(true) -, _textureUnitIndex(1) +, _textureUnitIndex(4) // first 4 textures unites are reserved for CC_Texture0-3 , _vertexAttribsFlags(0) , _glprogram(nullptr) , _nodeBinding(nullptr) diff --git a/cocos/renderer/CCMaterial.cpp b/cocos/renderer/CCMaterial.cpp index 57b0dbe6e6..06a618b957 100644 --- a/cocos/renderer/CCMaterial.cpp +++ b/cocos/renderer/CCMaterial.cpp @@ -198,9 +198,7 @@ bool Material::parsePass(Technique* technique, Properties* passProperties) while (space) { const char* name = space->getNamespace(); - if (strcmp(name, "sampler") == 0) - parseSampler(pass, space); - else if (strcmp(name, "shader") == 0) + if (strcmp(name, "shader") == 0) parseShader(pass, space); else if (strcmp(name, "renderState") == 0) parseRenderState(pass, space); @@ -216,10 +214,12 @@ bool Material::parsePass(Technique* technique, Properties* passProperties) } // cocos2d-x doesn't support Samplers yet. But will be added soon -bool Material::parseSampler(Pass* pass, Properties* textureProperties) +bool Material::parseSampler(GLProgramState* glProgramState, Properties* samplerProperties) { + CCASSERT(samplerProperties->getId(), "Sampler must have an id. The id is the uniform name"); + // required - auto filename = textureProperties->getString("path"); + auto filename = samplerProperties->getString("path"); auto texture = Director::getInstance()->getTextureCache()->addImage(filename); if (!texture) { @@ -234,14 +234,14 @@ bool Material::parseSampler(Pass* pass, Properties* textureProperties) // mipmap bool usemipmap = false; - const char* mipmap = getOptionalString(textureProperties, "mipmap", "false"); + const char* mipmap = getOptionalString(samplerProperties, "mipmap", "false"); if (mipmap && strcasecmp(mipmap, "true")==0) { texture->generateMipmap(); usemipmap = true; } // valid options: REPEAT, CLAMP - const char* wrapS = getOptionalString(textureProperties, "wrapS", "CLAMP_TO_EDGE"); + const char* wrapS = getOptionalString(samplerProperties, "wrapS", "CLAMP_TO_EDGE"); if (strcasecmp(wrapS, "REPEAT")==0) texParams.wrapS = GL_REPEAT; else if(strcasecmp(wrapS, "CLAMP_TO_EDGE")==0) @@ -251,7 +251,7 @@ bool Material::parseSampler(Pass* pass, Properties* textureProperties) // valid options: REPEAT, CLAMP - const char* wrapT = getOptionalString(textureProperties, "wrapT", "CLAMP_TO_EDGE"); + const char* wrapT = getOptionalString(samplerProperties, "wrapT", "CLAMP_TO_EDGE"); if (strcasecmp(wrapT, "REPEAT")==0) texParams.wrapT = GL_REPEAT; else if(strcasecmp(wrapT, "CLAMP_TO_EDGE")==0) @@ -261,7 +261,7 @@ bool Material::parseSampler(Pass* pass, Properties* textureProperties) // valid options: NEAREST, LINEAR, NEAREST_MIPMAP_NEAREST, LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR - const char* minFilter = getOptionalString(textureProperties, "minFilter", usemipmap ? "LINEAR_MIPMAP_NEAREST" : "LINEAR"); + const char* minFilter = getOptionalString(samplerProperties, "minFilter", usemipmap ? "LINEAR_MIPMAP_NEAREST" : "LINEAR"); if (strcasecmp(minFilter, "NEAREST")==0) texParams.minFilter = GL_NEAREST; else if(strcasecmp(minFilter, "LINEAR")==0) @@ -278,7 +278,7 @@ bool Material::parseSampler(Pass* pass, Properties* textureProperties) CCLOG("Invalid minFilter: %s", minFilter); // valid options: NEAREST, LINEAR - const char* magFilter = getOptionalString(textureProperties, "magFilter", "LINEAR"); + const char* magFilter = getOptionalString(samplerProperties, "magFilter", "LINEAR"); if (strcasecmp(magFilter, "NEAREST")==0) texParams.magFilter = GL_NEAREST; else if(strcasecmp(magFilter, "LINEAR")==0) @@ -289,7 +289,7 @@ bool Material::parseSampler(Pass* pass, Properties* textureProperties) texture->setTexParameters(texParams); } - pass->_textures.pushBack(texture); + glProgramState->setUniformTexture(samplerProperties->getId(), texture); return true; } @@ -321,7 +321,16 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties) property = shaderProperties->getNextProperty(); } -// glProgramState->updateUniformsAndAttributes(); + auto space = shaderProperties->getNextNamespace(); + while (space) + { + const char* name = space->getNamespace(); + if (strcmp(name, "sampler") == 0) + { + parseSampler(glProgramState, space); + } + space = shaderProperties->getNextNamespace(); + } } return true; diff --git a/cocos/renderer/CCMaterial.h b/cocos/renderer/CCMaterial.h index ddae8425dc..dde8591895 100644 --- a/cocos/renderer/CCMaterial.h +++ b/cocos/renderer/CCMaterial.h @@ -133,8 +133,8 @@ protected: bool parseProperties(Properties* properties); bool parseTechnique(Properties* properties); bool parsePass(Technique* technique, Properties* properties); - bool parseSampler(Pass* pass, Properties* properties); bool parseShader(Pass* pass, Properties* properties); + bool parseSampler(GLProgramState* glProgramState, Properties* properties); bool parseUniform(GLProgramState* programState, Properties* properties, const char* uniformName); bool parseRenderState(RenderState* renderState, Properties* properties); diff --git a/cocos/renderer/CCPass.cpp b/cocos/renderer/CCPass.cpp index 29dd7eff4c..2ac59e3092 100644 --- a/cocos/renderer/CCPass.cpp +++ b/cocos/renderer/CCPass.cpp @@ -129,7 +129,7 @@ uint32_t Pass::getHash() const { if (_hashDirty || _state->isDirty()) { uint32_t glProgram = (uint32_t)_glProgramState->getGLProgram()->getProgram(); - uint32_t textureid = (uint32_t)_textures.at(0)->getName(); + uint32_t textureid = _texture ? _texture->getName() : -1; uint32_t stateblockid = _state->getHash(); _hash = glProgram ^ textureid ^ stateblockid; diff --git a/cocos/renderer/CCRenderState.cpp b/cocos/renderer/CCRenderState.cpp index d67482e4a4..d0fb9e45f1 100644 --- a/cocos/renderer/CCRenderState.cpp +++ b/cocos/renderer/CCRenderState.cpp @@ -58,7 +58,7 @@ enum RenderState::RenderState() -: _textures() +: _texture(nullptr) , _hash(0) , _hashDirty(true) , _parent(nullptr) @@ -102,32 +102,27 @@ std::string RenderState::getName() const } -const Vector& RenderState::getTextures() const -{ - return _textures; -} - void RenderState::setTexture(Texture2D* texture) { - if (_textures.size() > 0) - _textures.replace(0, texture); - else - _textures.pushBack(texture); + if (_texture != texture) + { + CC_SAFE_RELEASE(_texture); + _texture = texture; + CC_SAFE_RETAIN(_texture); + } } Texture2D* RenderState::getTexture() const { - if (_textures.size() > 0) - return _textures.at(0); - return nullptr; + return _texture; } void RenderState::bind(Pass* pass) { CC_ASSERT(pass); - if (_textures.size() > 0) - GL::bindTexture2D(_textures.at(0)->getName()); + if (_texture) + GL::bindTexture2D(_texture->getName()); // Get the combined modified state bits for our RenderState hierarchy. long stateOverrideBits = _state ? _state->_bits : 0; @@ -193,7 +188,8 @@ void RenderState::cloneInto(RenderState* renderState) const } renderState->_name = _name; - renderState->_textures = _textures; + renderState->_texture = _texture; + CC_SAFE_RETAIN(renderState->_texture); // weak ref. don't retain renderState->_parent = _parent; } diff --git a/cocos/renderer/CCRenderState.h b/cocos/renderer/CCRenderState.h index 088db5621c..3f3a68eb11 100644 --- a/cocos/renderer/CCRenderState.h +++ b/cocos/renderer/CCRenderState.h @@ -31,7 +31,6 @@ #include #include -#include "renderer/CCTexture2D.h" #include "platform/CCPlatformMacros.h" #include "base/CCRef.h" #include "base/ccTypes.h" @@ -65,14 +64,12 @@ public: std::string getName() const; - const Vector& getTextures() const; - - /** Replaces the texture that is at the front of _textures array. - Added to be backwards compatible. + /** Texture that will use in the CC_Texture0 uniform. + Added to be backwards compatible. Use Samplers from .material instead. */ void setTexture(Texture2D* texture); - /** Returns the texture that is at the front of the _textures array. + /** Returns the texture that is going to be used for CC_Texture0. Added to be backwards compatible. */ Texture2D* getTexture() const; @@ -413,7 +410,7 @@ protected: // name, for filtering std::string _name; - Vector _textures; + Texture2D* _texture; }; NS_CC_END diff --git a/tests/cpp-tests/Resources/Materials/3d_effects.material b/tests/cpp-tests/Resources/Materials/3d_effects.material index aab208a426..39e3ad0d50 100644 --- a/tests/cpp-tests/Resources/Materials/3d_effects.material +++ b/tests/cpp-tests/Resources/Materials/3d_effects.material @@ -22,19 +22,20 @@ material spaceship // renderState: // resposinble for depth buffer, cullface, stencil, blending, etc. // shader: - // responsible for the vertex and frag shaders, and its uniforms - // sampler: - // responsible for setting the texture and its parameters + // responsible for the vertex and frag shaders, and its uniforms, including the samplers pass 0 { shader { vertexShader = Shaders3D/3d_position_tex.vert fragmentShader = Shaders3D/3d_color_tex.frag - } - sampler 0 - { - path = Sprite3DTest/boss.png + // sampler: + // responsible for setting the texture and its parameters + // the Id of the sampler is the uniform name + sampler u_sampler0 + { + path = Sprite3DTest/boss.png + } } } } @@ -61,10 +62,6 @@ material spaceship OutLineColor = 1,1,0 OutlineWidth = 0.04 } - sampler 0 - { - path = Sprite3DTest/boss.png - } } // 2nd pass: @@ -85,10 +82,6 @@ material spaceship OutLineColor = 0,0,1 OutlineWidth = 0.02 } - sampler 0 - { - path = Sprite3DTest/boss.png - } } // 3rd pass // Renders the model "normally" @@ -99,10 +92,10 @@ material spaceship { vertexShader = Shaders3D/3d_position_tex.vert fragmentShader = Shaders3D/3d_color_tex.frag - } - sampler 0 - { - path = Sprite3DTest/boss.png + sampler u_sampler0 + { + path = Sprite3DTest/boss.png + } } } } @@ -118,10 +111,10 @@ material spaceship defines = MAX_POINT_LIGHT_NUM 1;MAX_SPOT_LIGHT_NUM 1;MAX_DIRECTIONAL_LIGHT_NUM 1 vertexShader = Shaders3D/3d_position_normal_tex.vert fragmentShader = Shaders3D/3d_color_normal_tex.frag - } - sampler 0 - { - path = Sprite3DTest/boss.png + sampler u_sampler0 + { + path = Sprite3DTest/boss.png + } } } } diff --git a/tests/cpp-tests/Resources/Shaders3D/3d_color_normal_tex.frag b/tests/cpp-tests/Resources/Shaders3D/3d_color_normal_tex.frag index 3ffac456e1..e9ec20ed96 100644 --- a/tests/cpp-tests/Resources/Shaders3D/3d_color_normal_tex.frag +++ b/tests/cpp-tests/Resources/Shaders3D/3d_color_normal_tex.frag @@ -43,6 +43,7 @@ varying vec3 v_normal; #endif uniform vec4 u_color; +uniform sampler2D u_sampler0; vec3 computeLighting(vec3 normalVector, vec3 lightDirection, vec3 lightColor, float attenuation) { @@ -101,9 +102,9 @@ void main(void) #endif #if ((MAX_DIRECTIONAL_LIGHT_NUM > 0) || (MAX_POINT_LIGHT_NUM > 0) || (MAX_SPOT_LIGHT_NUM > 0)) - gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color * combinedColor; + gl_FragColor = texture2D(u_sampler0, TextureCoordOut) * u_color * combinedColor; #else - gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color; + gl_FragColor = texture2D(u_sampler0, TextureCoordOut) * u_color; #endif } diff --git a/tests/cpp-tests/Resources/Shaders3D/3d_color_tex.frag b/tests/cpp-tests/Resources/Shaders3D/3d_color_tex.frag index 0d87c7e229..9808ded895 100644 --- a/tests/cpp-tests/Resources/Shaders3D/3d_color_tex.frag +++ b/tests/cpp-tests/Resources/Shaders3D/3d_color_tex.frag @@ -4,9 +4,10 @@ varying mediump vec2 TextureCoordOut; varying vec2 TextureCoordOut; #endif uniform vec4 u_color; +uniform sampler2D u_sampler0; void main(void) { - gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color; + gl_FragColor = texture2D(u_sampler0, TextureCoordOut) * u_color; } diff --git a/tests/cpp-tests/Resources/Shaders3D/OutLine.vert b/tests/cpp-tests/Resources/Shaders3D/OutLine.vert index f4cd386b34..deafa4d387 100644 --- a/tests/cpp-tests/Resources/Shaders3D/OutLine.vert +++ b/tests/cpp-tests/Resources/Shaders3D/OutLine.vert @@ -8,6 +8,6 @@ void main(void) vec4 normalproj = CC_MVPMatrix * vec4(a_normal, 0); normalproj = normalize(normalproj); pos.xy += normalproj.xy * (OutlineWidth * (pos.z * 0.5 + 0.5)); - + gl_Position = pos; }