From 71848aca93b0484a51f04aee0c6756f272d474cb Mon Sep 17 00:00:00 2001 From: Ricardo Quesada Date: Mon, 12 May 2014 23:51:37 -0700 Subject: [PATCH] Initial multitexturing support --- cocos/renderer/CCGLProgram.cpp | 34 ++++++++++---------- cocos/renderer/CCGLProgramState.cpp | 50 +++++++++++++++++++++++------ cocos/renderer/CCGLProgramState.h | 16 +++++++-- cocos/renderer/CCQuadCommand.cpp | 4 +-- cocos/renderer/CCQuadCommand.h | 2 +- cocos/renderer/CCRenderer.cpp | 2 +- 6 files changed, 76 insertions(+), 32 deletions(-) diff --git a/cocos/renderer/CCGLProgram.cpp b/cocos/renderer/CCGLProgram.cpp index 43a2f09e43..9bc582d0dd 100644 --- a/cocos/renderer/CCGLProgram.cpp +++ b/cocos/renderer/CCGLProgram.cpp @@ -328,7 +328,7 @@ void GLProgram::parseUniforms() glGetActiveUniform(_program, i, length, NULL, &uniform.size, &uniform.type, uniformName); uniformName[length] = '\0'; - // Only add uniforms that are not build-in. + // Only add uniforms that are not built-in. // The ones that start with 'CC_' are built-ins if(strncmp("CC_", uniformName, 3) != 0) { @@ -617,7 +617,7 @@ GLint GLProgram::getUniformLocationForName(const char* name) const void GLProgram::setUniformLocationWith1i(GLint location, GLint i1) { - bool updated = updateUniformLocation(location, &i1, sizeof(i1)*1); + bool updated = updateUniformLocation(location, &i1, sizeof(i1)*1); if( updated ) { @@ -628,7 +628,7 @@ void GLProgram::setUniformLocationWith1i(GLint location, GLint i1) void GLProgram::setUniformLocationWith2i(GLint location, GLint i1, GLint i2) { GLint ints[2] = {i1,i2}; - bool updated = updateUniformLocation(location, ints, sizeof(ints)); + bool updated = updateUniformLocation(location, ints, sizeof(ints)); if( updated ) { @@ -639,7 +639,7 @@ void GLProgram::setUniformLocationWith2i(GLint location, GLint i1, GLint i2) void GLProgram::setUniformLocationWith3i(GLint location, GLint i1, GLint i2, GLint i3) { GLint ints[3] = {i1,i2,i3}; - bool updated = updateUniformLocation(location, ints, sizeof(ints)); + bool updated = updateUniformLocation(location, ints, sizeof(ints)); if( updated ) { @@ -650,7 +650,7 @@ void GLProgram::setUniformLocationWith3i(GLint location, GLint i1, GLint i2, GLi void GLProgram::setUniformLocationWith4i(GLint location, GLint i1, GLint i2, GLint i3, GLint i4) { GLint ints[4] = {i1,i2,i3,i4}; - bool updated = updateUniformLocation(location, ints, sizeof(ints)); + bool updated = updateUniformLocation(location, ints, sizeof(ints)); if( updated ) { @@ -660,7 +660,7 @@ void GLProgram::setUniformLocationWith4i(GLint location, GLint i1, GLint i2, GLi void GLProgram::setUniformLocationWith2iv(GLint location, GLint* ints, unsigned int numberOfArrays) { - bool updated = updateUniformLocation(location, ints, sizeof(int)*2*numberOfArrays); + bool updated = updateUniformLocation(location, ints, sizeof(int)*2*numberOfArrays); if( updated ) { @@ -670,7 +670,7 @@ void GLProgram::setUniformLocationWith2iv(GLint location, GLint* ints, unsigned void GLProgram::setUniformLocationWith3iv(GLint location, GLint* ints, unsigned int numberOfArrays) { - bool updated = updateUniformLocation(location, ints, sizeof(int)*3*numberOfArrays); + bool updated = updateUniformLocation(location, ints, sizeof(int)*3*numberOfArrays); if( updated ) { @@ -680,7 +680,7 @@ void GLProgram::setUniformLocationWith3iv(GLint location, GLint* ints, unsigned void GLProgram::setUniformLocationWith4iv(GLint location, GLint* ints, unsigned int numberOfArrays) { - bool updated = updateUniformLocation(location, ints, sizeof(int)*4*numberOfArrays); + bool updated = updateUniformLocation(location, ints, sizeof(int)*4*numberOfArrays); if( updated ) { @@ -690,7 +690,7 @@ void GLProgram::setUniformLocationWith4iv(GLint location, GLint* ints, unsigned void GLProgram::setUniformLocationWith1f(GLint location, GLfloat f1) { - bool updated = updateUniformLocation(location, &f1, sizeof(f1)*1); + bool updated = updateUniformLocation(location, &f1, sizeof(f1)*1); if( updated ) { @@ -712,7 +712,7 @@ void GLProgram::setUniformLocationWith2f(GLint location, GLfloat f1, GLfloat f2) void GLProgram::setUniformLocationWith3f(GLint location, GLfloat f1, GLfloat f2, GLfloat f3) { GLfloat floats[3] = {f1,f2,f3}; - bool updated = updateUniformLocation(location, floats, sizeof(floats)); + bool updated = updateUniformLocation(location, floats, sizeof(floats)); if( updated ) { @@ -723,7 +723,7 @@ void GLProgram::setUniformLocationWith3f(GLint location, GLfloat f1, GLfloat f2, void GLProgram::setUniformLocationWith4f(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4) { GLfloat floats[4] = {f1,f2,f3,f4}; - bool updated = updateUniformLocation(location, floats, sizeof(floats)); + bool updated = updateUniformLocation(location, floats, sizeof(floats)); if( updated ) { @@ -733,7 +733,7 @@ void GLProgram::setUniformLocationWith4f(GLint location, GLfloat f1, GLfloat f2, void GLProgram::setUniformLocationWith2fv(GLint location, const GLfloat* floats, unsigned int numberOfArrays) { - bool updated = updateUniformLocation(location, floats, sizeof(float)*2*numberOfArrays); + bool updated = updateUniformLocation(location, floats, sizeof(float)*2*numberOfArrays); if( updated ) { @@ -743,7 +743,7 @@ void GLProgram::setUniformLocationWith2fv(GLint location, const GLfloat* floats, void GLProgram::setUniformLocationWith3fv(GLint location, const GLfloat* floats, unsigned int numberOfArrays) { - bool updated = updateUniformLocation(location, floats, sizeof(float)*3*numberOfArrays); + bool updated = updateUniformLocation(location, floats, sizeof(float)*3*numberOfArrays); if( updated ) { @@ -753,7 +753,7 @@ void GLProgram::setUniformLocationWith3fv(GLint location, const GLfloat* floats, void GLProgram::setUniformLocationWith4fv(GLint location, const GLfloat* floats, unsigned int numberOfArrays) { - bool updated = updateUniformLocation(location, floats, sizeof(float)*4*numberOfArrays); + bool updated = updateUniformLocation(location, floats, sizeof(float)*4*numberOfArrays); if( updated ) { @@ -762,7 +762,7 @@ void GLProgram::setUniformLocationWith4fv(GLint location, const GLfloat* floats, } void GLProgram::setUniformLocationWithMatrix2fv(GLint location, const GLfloat* matrixArray, unsigned int numberOfMatrices) { - bool updated = updateUniformLocation(location, matrixArray, sizeof(float)*4*numberOfMatrices); + bool updated = updateUniformLocation(location, matrixArray, sizeof(float)*4*numberOfMatrices); if( updated ) { @@ -771,7 +771,7 @@ void GLProgram::setUniformLocationWithMatrix2fv(GLint location, const GLfloat* m } void GLProgram::setUniformLocationWithMatrix3fv(GLint location, const GLfloat* matrixArray, unsigned int numberOfMatrices) { - bool updated = updateUniformLocation(location, matrixArray, sizeof(float)*9*numberOfMatrices); + bool updated = updateUniformLocation(location, matrixArray, sizeof(float)*9*numberOfMatrices); if( updated ) { @@ -782,7 +782,7 @@ void GLProgram::setUniformLocationWithMatrix3fv(GLint location, const GLfloat* m void GLProgram::setUniformLocationWithMatrix4fv(GLint location, const GLfloat* matrixArray, unsigned int numberOfMatrices) { - bool updated = updateUniformLocation(location, matrixArray, sizeof(float)*16*numberOfMatrices); + bool updated = updateUniformLocation(location, matrixArray, sizeof(float)*16*numberOfMatrices); if( updated ) { diff --git a/cocos/renderer/CCGLProgramState.cpp b/cocos/renderer/CCGLProgramState.cpp index f578ce20fe..36218d8c91 100644 --- a/cocos/renderer/CCGLProgramState.cpp +++ b/cocos/renderer/CCGLProgramState.cpp @@ -31,6 +31,7 @@ THE SOFTWARE. #include "renderer/CCGLProgramStateCache.h" #include "renderer/CCGLProgramCache.h" #include "renderer/ccGLStateCache.h" +#include "2d/CCTexture2D.h" NS_CC_BEGIN @@ -68,15 +69,20 @@ void UniformValue::apply() else { switch (_uniform->type) { - case GL_FLOAT: - _glprogram->setUniformLocationWith1f(_uniform->location, _value.floatValue); + case GL_SAMPLER_2D: + _glprogram->setUniformLocationWith1i(_uniform->location, _value.tex.textureUnit); + GL::activeTexture(_value.tex.textureUnit); + GL::bindTexture2DN(_value.tex.textureUnit, _value.tex.textureId); break; case GL_INT: - case GL_SAMPLER_2D: _glprogram->setUniformLocationWith1i(_uniform->location, _value.intValue); break; + case GL_FLOAT: + _glprogram->setUniformLocationWith1f(_uniform->location, _value.floatValue); + break; + case GL_FLOAT_VEC2: _glprogram->setUniformLocationWith2f(_uniform->location, _value.v2Value[0], _value.v2Value[1]); break; @@ -122,9 +128,16 @@ void UniformValue::setFloat(float value) _useCallback = false; } +void UniformValue::setTexture(GLuint textureId, GLuint textureUnit) +{ + CCASSERT(_uniform->type == GL_SAMPLER_2D, "Wrong type. expecting GL_SAMPLER_2D"); + _value.tex.textureId = textureId; + _value.tex.textureUnit = textureUnit; + _useCallback = false; +} void UniformValue::setInt(int value) { - CCASSERT ((_uniform->type == GL_INT || _uniform->type == GL_SAMPLER_2D), ""); + CCASSERT(_uniform->type == GL_INT, "Wrong type: expecting GL_INT"); _value.intValue = value; _useCallback = false; } @@ -255,6 +268,7 @@ GLProgramState* GLProgramState::getOrCreate(GLProgram *glprogram) GLProgramState::GLProgramState() : _vertexAttribsFlags(0) , _glprogram(nullptr) +, _textureUnitIndex(1) { } @@ -288,6 +302,8 @@ void GLProgramState::resetGLProgram() CC_SAFE_RELEASE(_glprogram); _uniforms.clear(); _attributes.clear(); + // first texture is GL_TEXTURE1 + _textureUnitIndex = 1; } void GLProgramState::apply(const Matrix& modelView) @@ -296,12 +312,10 @@ void GLProgramState::apply(const Matrix& modelView) // set shader _glprogram->use(); - _glprogram->setUniformsForBuiltins(modelView); - - // quick hack: - // Don't deal with attributes if they were set + // Don't set attributes if they weren't set + // Use Case: Auto-batching if(_vertexAttribsFlags) { // enable/disable vertex attribs GL::enableVertexAttribs(_vertexAttribsFlags); @@ -320,7 +334,7 @@ void GLProgramState::apply(const Matrix& modelView) void GLProgramState::setGLProgram(GLProgram *glprogram) { - CCASSERT(glprogram, "invalid GLProgram"); + CCASSERT(glprogram, "invalid GLProgram"); if( _glprogram != glprogram) { resetGLProgram(); @@ -439,4 +453,22 @@ void GLProgramState::setUniformMat4(const std::string &uniformName, const Matrix CCLOG("cocos2d: warning: Uniform not found: %s", uniformName.c_str()); } +// Textures + +void GLProgramState::setUniformTexture(const std::string &uniformName, Texture2D *texture) +{ + CCASSERT(texture, "Invalid texture"); + setUniformTexture(uniformName, texture->getName()); +} + +void GLProgramState::setUniformTexture(const std::string &uniformName, GLuint textureId) +{ + auto v = getUniformValue(uniformName); + if (v) + v->setTexture(textureId, _textureUnitIndex++); + else + CCLOG("cocos2d: warning: Uniform not found: %s", uniformName.c_str()); +} + + NS_CC_END diff --git a/cocos/renderer/CCGLProgramState.h b/cocos/renderer/CCGLProgramState.h index 1aca92a3d3..9f7f6153ce 100644 --- a/cocos/renderer/CCGLProgramState.h +++ b/cocos/renderer/CCGLProgramState.h @@ -32,10 +32,13 @@ THE SOFTWARE. #include "math/Vector4.h" #include +#include + NS_CC_BEGIN class GLProgram; +class Texture2D; struct Uniform; struct VertexAttrib; @@ -60,6 +63,7 @@ public: void setVec4(const Vector4& value); void setMat4(const Matrix& value); void setCallback(const std::function &callback); + void setTexture(GLuint textureId, GLuint activeTexture); void apply(); @@ -75,6 +79,10 @@ protected: float v3Value[3]; float v4Value[4]; float matrixValue[16]; + struct { + GLuint textureId; + GLuint textureUnit; + } tex; std::function *callback; U() { memset( this, 0, sizeof(*this) ); } @@ -154,20 +162,23 @@ public: void setGLProgram(GLProgram* glprogram); GLProgram* getGLProgram() const { return _glprogram; } + // vertex attribs uint32_t getVertexAttribsFlags() const { return _vertexAttribsFlags; } ssize_t getVertexAttribCount() const { return _attributes.size(); } void setVertexAttribCallback(const std::string &name, const std::function &callback); void setVertexAttribPointer(const std::string &name, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLvoid *pointer); + // user defined uniforms ssize_t getUniformCount() const { return _uniforms.size(); } - void setUniformFloat(const std::string &uniformName, float value); void setUniformInt(const std::string &uniformName, int value); + void setUniformFloat(const std::string &uniformName, float value); void setUniformVec2(const std::string &uniformName, const Vector2& value); void setUniformVec3(const std::string &uniformName, const Vector3& value); void setUniformVec4(const std::string &uniformName, const Vector4& value); void setUniformMat4(const std::string &uniformName, const Matrix& value); void setUniformCallback(const std::string &uniformName, const std::function &callback); - + void setUniformTexture(const std::string &uniformName, Texture2D *texture); + void setUniformTexture(const std::string &uniformName, GLuint textureId); protected: GLProgramState(); @@ -180,6 +191,7 @@ protected: std::unordered_map _uniforms; std::unordered_map _attributes; + int _textureUnitIndex; uint32_t _vertexAttribsFlags; GLProgram *_glprogram; }; diff --git a/cocos/renderer/CCQuadCommand.cpp b/cocos/renderer/CCQuadCommand.cpp index 495d2b3cb7..9eb8cc19cb 100644 --- a/cocos/renderer/CCQuadCommand.cpp +++ b/cocos/renderer/CCQuadCommand.cpp @@ -72,9 +72,9 @@ QuadCommand::~QuadCommand() void QuadCommand::generateMaterialID() { - if( _glProgramState->getUniformCount() > 0 ) + if(_glProgramState->getUniformCount() > 0) { - _materialID = QuadCommand::MATERIAL_ID_IGNORE; + _materialID = QuadCommand::MATERIAL_ID_DO_NOT_BATCH; } else { diff --git a/cocos/renderer/CCQuadCommand.h b/cocos/renderer/CCQuadCommand.h index 601aab442b..c838f2bc32 100644 --- a/cocos/renderer/CCQuadCommand.h +++ b/cocos/renderer/CCQuadCommand.h @@ -35,7 +35,7 @@ NS_CC_BEGIN class QuadCommand : public RenderCommand { public: - static const int MATERIAL_ID_IGNORE = 0; + static const int MATERIAL_ID_DO_NOT_BATCH = 0; QuadCommand(); ~QuadCommand(); diff --git a/cocos/renderer/CCRenderer.cpp b/cocos/renderer/CCRenderer.cpp index 8282eb168f..5246f6efb5 100644 --- a/cocos/renderer/CCRenderer.cpp +++ b/cocos/renderer/CCRenderer.cpp @@ -453,7 +453,7 @@ void Renderer::drawBatchedQuads() for(const auto& cmd : _batchedQuadCommands) { auto newMaterialID = cmd->getMaterialID(); - if(_lastMaterialID != newMaterialID || newMaterialID == QuadCommand::MATERIAL_ID_IGNORE) + if(_lastMaterialID != newMaterialID || newMaterialID == QuadCommand::MATERIAL_ID_DO_NOT_BATCH) { //Draw quads if(quadsToDraw > 0)