From d2a57239739d362dadf02f67335bde02bc69a20e Mon Sep 17 00:00:00 2001 From: minggo Date: Fri, 9 Nov 2012 12:08:18 +0800 Subject: [PATCH] issue #1555:add CCDrawNode --- cocos2dx/CCDirector.cpp | 1 - cocos2dx/base_nodes/CCNode.cpp | 18 +- cocos2dx/draw_nodes/CCDrawNode.cpp | 154 +++++++++++++ cocos2dx/draw_nodes/CCDrawNode.h | 88 +++++++ .../{ => draw_nodes}/CCDrawingPrimitives.cpp | 18 +- .../{ => draw_nodes}/CCDrawingPrimitives.h | 0 cocos2dx/effects/CCGrid.cpp | 4 +- cocos2dx/include/ccMacros.h | 2 +- cocos2dx/include/cocos2d.h | 3 + .../CCLayer.cpp | 2 +- cocos2dx/misc_nodes/CCClippingNode.cpp | 34 +++ cocos2dx/misc_nodes/CCClippingNode.h | 8 +- .../project.pbxproj.REMOVED.git-id | 2 +- cocos2dx/shaders/CCGLProgram.cpp | 216 ++++++++++++------ cocos2dx/shaders/CCGLProgram.h | 76 +++--- cocos2dx/shaders/ccGLStateCache.cpp | 118 ++++++---- cocos2dx/shaders/ccGLStateCache.h | 51 +++-- cocos2dx/textures/CCTexture2D.cpp | 4 +- 18 files changed, 609 insertions(+), 190 deletions(-) create mode 100644 cocos2dx/draw_nodes/CCDrawNode.cpp create mode 100644 cocos2dx/draw_nodes/CCDrawNode.h rename cocos2dx/{ => draw_nodes}/CCDrawingPrimitives.cpp (96%) rename cocos2dx/{ => draw_nodes}/CCDrawingPrimitives.h (100%) diff --git a/cocos2dx/CCDirector.cpp b/cocos2dx/CCDirector.cpp index 638111a0b5..d06204dd55 100644 --- a/cocos2dx/CCDirector.cpp +++ b/cocos2dx/CCDirector.cpp @@ -403,7 +403,6 @@ void CCDirector::setAlphaBlending(bool bOn) { if (bOn) { - ccGLEnable(CC_GL_BLEND); ccGLBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); } else diff --git a/cocos2dx/base_nodes/CCNode.cpp b/cocos2dx/base_nodes/CCNode.cpp index 08e8a4ff11..23c87afff2 100644 --- a/cocos2dx/base_nodes/CCNode.cpp +++ b/cocos2dx/base_nodes/CCNode.cpp @@ -82,7 +82,7 @@ CCNode::CCNode(void) , m_nScriptHandler(0) , m_pShaderProgram(NULL) , m_nOrderOfArrival(0) -, m_glServerState(CC_GL_BLEND) +, m_glServerState(ccGLServerState(0)) , m_bReorderChildDirty(false) { // set default scheduler and actionManager @@ -537,9 +537,9 @@ void CCNode::addChild(CCNode *child) this->addChild(child, child->m_nZOrder, child->m_nTag); } -void CCNode::removeFromParent() -{ - this->removeFromParentAndCleanup(true); +void CCNode::removeFromParent() +{ + this->removeFromParentAndCleanup(true); } void CCNode::removeFromParentAndCleanup(bool cleanup) @@ -1144,11 +1144,11 @@ CCPoint CCNode::convertTouchToNodeSpaceAR(CCTouch *touch) return this->convertToNodeSpaceAR(point); } -// MARMALADE ADDED -void CCNode::updateTransform() -{ - // Recursively iterate over children - arrayMakeObjectsPerformSelector(m_pChildren, updateTransform, CCNode*); +// MARMALADE ADDED +void CCNode::updateTransform() +{ + // Recursively iterate over children + arrayMakeObjectsPerformSelector(m_pChildren, updateTransform, CCNode*); } NS_CC_END diff --git a/cocos2dx/draw_nodes/CCDrawNode.cpp b/cocos2dx/draw_nodes/CCDrawNode.cpp new file mode 100644 index 0000000000..f758c218c6 --- /dev/null +++ b/cocos2dx/draw_nodes/CCDrawNode.cpp @@ -0,0 +1,154 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * Copyright (c) 2012 cocos2d-x.org + * + * 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. + */ + +#include "CCDrawNode.h" +#include "support/CCPointExtension.h" +#include "shaders/CCShaderCache.h" + +NS_CC_BEGIN + +// ccVertex2F == CGPoint in 32-bits, but not in 64-bits (OS X) +// that's why the "v2f" functions are needed +static ccVertex2F v2fzero = (ccVertex2F){0,0}; + +static inline ccVertex2F v2f(float x, float y) +{ + return (ccVertex2F){x,y}; +} + +static inline ccVertex2F v2fadd(const ccVertex2F &v0, const ccVertex2F &v1) +{ + return v2f(v0.x+v1.x, v0.y+v1.y); +} + +static inline ccVertex2F v2fsub(const ccVertex2F &v0, const ccVertex2F &v1) +{ + return v2f(v0.x-v1.x, v0.y-v1.y); +} + +static inline ccVertex2F v2fmult(const ccVertex2F &v, float s) +{ + return v2f(v.x * s, v.y * s); +} + +static inline ccVertex2F v2fperp(const ccVertex2F &p0) +{ + return v2f(-p0.y, p0.x); +} + +static inline ccVertex2F v2fneg(const ccVertex2F &p0) +{ + return v2f(-p0.x, - p0.y); +} + +static inline float v2fdot(const ccVertex2F &p0, const ccVertex2F &p1) +{ + return p0.x * p1.x + p0.y * p1.y; +} + +static inline ccVertex2F v2fforangle(float _a_) +{ + return v2f(cosf(_a_), sinf(_a_)); +} + +static inline ccVertex2F v2fnormalize(const ccVertex2F &p) +{ + CCPoint r = ccpNormalize(ccp(p.x, p.y)); + return v2f(r.x, r.y); +} + +static inline ccVertex2F __v2f(const CCPoint &v) +{ +#ifdef __LP64__ + return v2f(v.x, v.y); +#else + return * ((ccVertex2F*) &v); +#endif +} + +static inline ccTex2F __t(const ccVertex2F &v) +{ + return *(ccTex2F*)&v; +} + +// implementation of CCDrawNode + +CCDrawNode::CCDrawNode() +: m_uVao(0) +, m_uVbo(0) +, m_uBufferCapacity(0) +, m_nBufferCount(0) +, m_pBuffer(NULL) +, m_sBlendFunc((ccBlendFunc){CC_BLEND_SRC, CC_BLEND_DST}) +, m_bDirty(false) +{} + +CCDrawNode* CCDrawNode::create() +{ + CCDrawNode* pRet = new CCDrawNode(); + if (pRet && pRet->init()) + { + pRet->autorelease(); + } + else + { + CC_SAFE_DELETE(pRet); + } + + return pRet; +} + +bool CCDrawNode::init() +{ + m_sBlendFunc = (ccBlendFunc){CC_BLEND_SRC, CC_BLEND_DST}; + + setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionLengthTexureColor)); + + ensureCapacity(512); + + glGenVertexArrays(1, &m_uVao); + ccGLBindVAO(m_uVao); + + glGenBuffers(1, &m_uVbo); + glBindBuffer(GL_ARRAY_BUFFER, m_uVbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(ccV2F_C4B_T2F)* m_uBufferCapacity, m_pBuffer, GL_STREAM_DRAW); + + glEnableVertexAttribArray(kCCVertexAttrib_Position); + glVertexAttribPointer(kCCVertexAttrib_Position, 2, GL_FLOAT, GL_FALSE, sizeof(ccV2F_C4B_T2F), (GLvoid *)offsetof(ccV2F_C4B_T2F, vertices)); + + glEnableVertexAttribArray(kCCVertexAttrib_Color); + glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ccV2F_C4B_T2F), (GLvoid *)offsetof(ccV2F_C4B_T2F, colors)); + + glEnableVertexAttribArray(kCCVertexAttrib_TexCoords); + glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, sizeof(ccV2F_C4B_T2F), (GLvoid *)offsetof(ccV2F_C4B_T2F, texCoords)); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + ccGLBindVAO(0); + + CHECK_GL_ERROR_DEBUG(); + + m_bDirty = true; + + return true; +} + +NS_CC_END diff --git a/cocos2dx/draw_nodes/CCDrawNode.h b/cocos2dx/draw_nodes/CCDrawNode.h new file mode 100644 index 0000000000..478e7e701e --- /dev/null +++ b/cocos2dx/draw_nodes/CCDrawNode.h @@ -0,0 +1,88 @@ +/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software + * Copyright (c) 2012 cocos2d-x.org + * + * 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. + */ + +/* + * Code copied & pasted from SpacePatrol game https://github.com/slembcke/SpacePatrol + * + * Renamed and added some changes for cocos2d + * + */ + +#ifndef __CCDRAWNODES_CCDRAW_NODE_H__ +#define __CCDRAWNODES_CCDRAW_NODE_H__ + +#include "base_nodes/CCNode.h" +#include "ccTypes.h" + +NS_CC_BEGIN + +/** CCDrawNode + Node that draws dots, segments and polygons. + Faster than the "drawing primitives" since they it draws everything in one single batch. + + @since v2.1 + */ +class CC_DLL CCDrawNode : public CCNode +{ +protected: + GLuint m_uVao; + GLuint m_uVbo; + + unsigned int m_uBufferCapacity; + GLsizei m_nBufferCount; + ccV2F_C4B_T2F *m_pBuffer; + + ccBlendFunc m_sBlendFunc; + + bool m_bDirty; + +public: + static CCDrawNode* create(); + ~CCDrawNode(); + + virtual bool init(); + virtual void draw(); + + /** draw a dot at a position, with a given radius and color */ + void drawDot(const CCPoint &pos, float radius, const ccColor4F &color) const; + + /** draw a segment with a radius and color */ + void drawSegment(const CCPoint &from, const CCPoint &to, float radius, const ccColor4F &color) const; + + /** draw a polygon with a fill color and line color */ + void drawPolygon(const CCPoint *verts, unsigned int count, const ccColor4F &fillColor, float borderWidth, const ccColor4F &borderColor) const; + + /** Clear the geometry in the node's buffer. */ + void clear(); + + ccBlendFunc getBlendFunc() const; + void setBlendFunc(const ccBlendFunc &blendFunc); + +private: + CCDrawNode(); + void ensureCapacity(unsigned int count); + void render(); +}; + +NS_CC_END + +#endif // __CCDRAWNODES_CCDRAW_NODE_H__ diff --git a/cocos2dx/CCDrawingPrimitives.cpp b/cocos2dx/draw_nodes/CCDrawingPrimitives.cpp similarity index 96% rename from cocos2dx/CCDrawingPrimitives.cpp rename to cocos2dx/draw_nodes/CCDrawingPrimitives.cpp index 574b4e3ac0..06df92e6e2 100644 --- a/cocos2dx/CCDrawingPrimitives.cpp +++ b/cocos2dx/draw_nodes/CCDrawingPrimitives.cpp @@ -83,7 +83,7 @@ void ccDrawPoint( const CCPoint& point ) ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize); @@ -101,7 +101,7 @@ void ccDrawPoints( const CCPoint *points, unsigned int numberOfPoints ) ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize); @@ -142,7 +142,7 @@ void ccDrawLine( const CCPoint& origin, const CCPoint& destination ) s_pShader->use(); CHECK_GL_ERROR_DEBUG(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); CHECK_GL_ERROR_DEBUG(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); CHECK_GL_ERROR_DEBUG(); @@ -181,7 +181,7 @@ void ccDrawPoly( const CCPoint *poli, unsigned int numberOfPoints, bool closePol lazy_init(); s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); @@ -223,7 +223,7 @@ void ccDrawSolidPoly( const CCPoint *poli, unsigned int numberOfPoints, ccColor4 lazy_init(); s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &color.r, 1); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); @@ -278,7 +278,7 @@ void ccDrawCircle( const CCPoint& center, float radius, float angle, unsigned in vertices[(segments+1)*2+1] = center.y; s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); @@ -313,7 +313,7 @@ void ccDrawQuadBezier(const CCPoint& origin, const CCPoint& control, const CCPoi vertices[segments].y = destination.y; s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); @@ -365,7 +365,7 @@ void ccDrawCardinalSpline( CCPointArray *config, float tension, unsigned int se } s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*)&s_tColor.r, 1); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); @@ -394,7 +394,7 @@ void ccDrawCubicBezier(const CCPoint& origin, const CCPoint& control1, const CCP vertices[segments].y = destination.y; s_pShader->use(); - s_pShader->setUniformForModelViewProjectionMatrix(); + s_pShader->setUniformsForBuiltins(); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); diff --git a/cocos2dx/CCDrawingPrimitives.h b/cocos2dx/draw_nodes/CCDrawingPrimitives.h similarity index 100% rename from cocos2dx/CCDrawingPrimitives.h rename to cocos2dx/draw_nodes/CCDrawingPrimitives.h diff --git a/cocos2dx/effects/CCGrid.cpp b/cocos2dx/effects/CCGrid.cpp index 3e09ce029c..c75de666bd 100644 --- a/cocos2dx/effects/CCGrid.cpp +++ b/cocos2dx/effects/CCGrid.cpp @@ -337,7 +337,7 @@ void CCGrid3D::blit(void) ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); m_pShaderProgram->use(); - m_pShaderProgram->setUniformForModelViewProjectionMatrix();; + m_pShaderProgram->setUniformsForBuiltins();; // // Attributes @@ -542,7 +542,7 @@ void CCTiledGrid3D::blit(void) m_pShaderProgram->use(); - m_pShaderProgram->setUniformForModelViewProjectionMatrix(); + m_pShaderProgram->setUniformsForBuiltins(); // // Attributes diff --git a/cocos2dx/include/ccMacros.h b/cocos2dx/include/ccMacros.h index a461b29fbb..991c7f6ef5 100644 --- a/cocos2dx/include/ccMacros.h +++ b/cocos2dx/include/ccMacros.h @@ -88,7 +88,7 @@ do { \ CCAssert(getShaderProgram(), "No shader program set for this node"); \ { \ getShaderProgram()->use(); \ - getShaderProgram()->setUniformForModelViewProjectionMatrix(); \ + getShaderProgram()->setUniformsForBuiltins(); \ } \ } while(0) diff --git a/cocos2dx/include/cocos2d.h b/cocos2dx/include/cocos2d.h index fea7298579..457ee70549 100755 --- a/cocos2dx/include/cocos2d.h +++ b/cocos2dx/include/cocos2d.h @@ -69,6 +69,9 @@ THE SOFTWARE. #include "cocoa/CCNS.h" #include "cocoa/CCZone.h" +// draw nodes +#include "draw_nodes/CCDrawingPrimitives.h" + // effects #include "effects/CCGrabber.h" #include "effects/CCGrid.h" diff --git a/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp b/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp index 2fdb2575b1..16ed44d1b8 100644 --- a/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp +++ b/cocos2dx/layers_scenes_transitions_nodes/CCLayer.cpp @@ -242,7 +242,7 @@ void CCLayer::setAccelerometerInterval(double interval) { { if (m_bIsRunning) { - CCDirector* pDirector = CCDirector::sharedDirector(); +// CCDirector* pDirector = CCDirector::sharedDirector(); // pDirector->getAccelerometer()->setAccelerometerInterval(interval); } } diff --git a/cocos2dx/misc_nodes/CCClippingNode.cpp b/cocos2dx/misc_nodes/CCClippingNode.cpp index c077ffef7e..74da7d1415 100644 --- a/cocos2dx/misc_nodes/CCClippingNode.cpp +++ b/cocos2dx/misc_nodes/CCClippingNode.cpp @@ -30,6 +30,8 @@ #include "shaders/CCGLProgram.h" #include "shaders/CCShaderCache.h" #include "CCDirector.h" +#include "support/CCPointExtension.h" +#include "draw_nodes/CCDrawingPrimitives.h" NS_CC_BEGIN @@ -358,4 +360,36 @@ void CCClippingNode::visit() layer--; } +CCNode* CCClippingNode::getStencil() const +{ + return m_pStencil; +} + +void CCClippingNode::setStencil(CCNode *pStencil) +{ + CC_SAFE_RELEASE(m_pStencil); + m_pStencil = pStencil; + CC_SAFE_RETAIN(m_pStencil); +} + +GLfloat CCClippingNode::getAlphaThreshold() const +{ + return m_fAlphaThreshold; +} + +void CCClippingNode::setAlphaThreshold(GLfloat fAlphaThreshold) +{ + m_fAlphaThreshold = fAlphaThreshold; +} + +bool CCClippingNode::isInverted() const +{ + return m_bInverted; +} + +void CCClippingNode::setInverted(bool bInverted) +{ + m_bInverted = bInverted; +} + NS_CC_END diff --git a/cocos2dx/misc_nodes/CCClippingNode.h b/cocos2dx/misc_nodes/CCClippingNode.h index 1d27af2d4a..804ae68ddb 100644 --- a/cocos2dx/misc_nodes/CCClippingNode.h +++ b/cocos2dx/misc_nodes/CCClippingNode.h @@ -76,7 +76,7 @@ public: The stencil node will be retained. This default to nil. */ - CCNode* getStencil(); + CCNode* getStencil() const; void setStencil(CCNode *pStencil); /** The alpha threshold. @@ -84,15 +84,15 @@ public: Should be a float between 0 and 1. This default to 1 (so alpha test is disabled). */ - GLfloat getAlphaThreshold(); + GLfloat getAlphaThreshold() const; void setAlphaThreshold(GLfloat fAlphaThreshold); /** Inverted. If this is set to YES, the stencil is inverted, so the content is drawn where the stencil is NOT drawn. This default to NO. */ - bool isInverted(); - bool setInverted(bool bInverted); + bool isInverted() const; + void setInverted(bool bInverted); private: CCClippingNode(); diff --git a/cocos2dx/proj.ios/cocos2dx.xcodeproj/project.pbxproj.REMOVED.git-id b/cocos2dx/proj.ios/cocos2dx.xcodeproj/project.pbxproj.REMOVED.git-id index 24ee0c4d63..6bbec37969 100644 --- a/cocos2dx/proj.ios/cocos2dx.xcodeproj/project.pbxproj.REMOVED.git-id +++ b/cocos2dx/proj.ios/cocos2dx.xcodeproj/project.pbxproj.REMOVED.git-id @@ -1 +1 @@ -a63972a39f79cdc3fd02e88518f0e17da54554ae \ No newline at end of file +2ca5fe7b3dd190dca76cc6d572d7c910f560e9ff \ No newline at end of file diff --git a/cocos2dx/shaders/CCGLProgram.cpp b/cocos2dx/shaders/CCGLProgram.cpp index 7b6ecf4428..5cf8305ef4 100644 --- a/cocos2dx/shaders/CCGLProgram.cpp +++ b/cocos2dx/shaders/CCGLProgram.cpp @@ -25,6 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ +#include "CCDirector.h" #include "CCGLProgram.h" #include "ccGLStateCache.h" #include "ccMacros.h" @@ -58,8 +59,8 @@ CCGLProgram::~CCGLProgram() CCLOGINFO("cocos2d: %s %d deallocing 0x%X", __FUNCTION__, __LINE__, this); // there is no need to delete the shaders. They should have been already deleted. - CCAssert( m_uVertShader == 0, "Vertex Shaders should have been already deleted"); - CCAssert( m_uFragShader == 0, "Vertex Shaders should have been already deleted"); + CCAssert(m_uVertShader == 0, "Vertex Shaders should have been already deleted"); + CCAssert(m_uFragShader == 0, "Fragment Shaders should have been already deleted"); if (m_uProgram) { @@ -69,7 +70,8 @@ CCGLProgram::~CCGLProgram() tHashUniformEntry *current_element, *tmp; // Purge uniform hash - HASH_ITER(hh, m_pHashForUniforms, current_element, tmp) { + HASH_ITER(hh, m_pHashForUniforms, current_element, tmp) + { HASH_DEL(m_pHashForUniforms, current_element); free(current_element->value); free(current_element); @@ -83,28 +85,34 @@ bool CCGLProgram::initWithVertexShaderByteArray(const GLchar* vShaderByteArray, m_uVertShader = m_uFragShader = 0; - if( vShaderByteArray ) { + if (vShaderByteArray) + { - if (!compileShader(&m_uVertShader, GL_VERTEX_SHADER, vShaderByteArray)) { + if (!compileShader(&m_uVertShader, GL_VERTEX_SHADER, vShaderByteArray)) + { CCLOG("cocos2d: ERROR: Failed to compile vertex shader"); } } // Create and compile fragment shader - if( fShaderByteArray ) { + if (fShaderByteArray) + { - if (!compileShader(&m_uFragShader, GL_FRAGMENT_SHADER, fShaderByteArray)) { + if (!compileShader(&m_uFragShader, GL_FRAGMENT_SHADER, fShaderByteArray)) + { CCLOG("cocos2d: ERROR: Failed to compile fragment shader"); } } - if( m_uVertShader ) { + if (m_uVertShader) + { glAttachShader(m_uProgram, m_uVertShader); } CHECK_GL_ERROR_DEBUG(); - if( m_uFragShader ) { + if (m_uFragShader) + { glAttachShader(m_uProgram, m_uFragShader); } m_pHashForUniforms = NULL; @@ -132,10 +140,27 @@ bool CCGLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* sour GLint status; if (!source) + { return false; + } + + const GLchar *sources[] = { +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) + (type == GL_VERTEX_SHADER ? "precision highp float;\n" : "precision mediump float;\n"), +#endif + "uniform mat4 CC_PMatrix;\n" + "uniform mat4 CC_MVMatrix;\n" + "uniform mat4 CC_MVPMatrix;\n" + "uniform vec4 CC_Time;\n" + "uniform vec4 CC_SinTime;\n" + "uniform vec4 CC_CosTime;\n" + "uniform vec4 CC_Random01;\n" + "//CC INCLUDES END\n\n", + source, + }; *shader = glCreateShader(type); - glShaderSource(*shader, 1, &source, NULL); + glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, NULL); CHECK_GL_ERROR_DEBUG(); glCompileShader(*shader); CHECK_GL_ERROR_DEBUG(); @@ -143,64 +168,93 @@ bool CCGLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* sour glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); CHECK_GL_ERROR_DEBUG(); - if( ! status ) { - if( type == GL_VERTEX_SHADER ) - CCLOG("cocos2d: %s", vertexShaderLog() ); + if (! status) + { + GLsizei length; + glGetShaderiv(*shader, GL_SHADER_SOURCE_LENGTH, &length); + GLchar src[length]; + + glGetShaderSource(*shader, length, NULL, src); + CCLOG("cocos2d: ERROR: Failed to compile shader:\n%s", src); + + if (type == GL_VERTEX_SHADER) + { + CCLOG("cocos2d: %s", vertexShaderLog()); + } else - CCLOG("cocos2d: %s", fragmentShaderLog() ); + { + CCLOG("cocos2d: %s", fragmentShaderLog()); + } + + abort(); } return ( status == GL_TRUE ); } void CCGLProgram::addAttribute(const char* attributeName, GLuint index) { - glBindAttribLocation(m_uProgram, - index, - attributeName); + glBindAttribLocation(m_uProgram, index, attributeName); } void CCGLProgram::updateUniforms() { - // Since sample most probably won't change, set it to 0 now. - - m_uUniforms[kCCUniformMVPMatrix] = glGetUniformLocation(m_uProgram, kCCUniformMVPMatrix_s); + m_uUniforms[kCCUniformPMatrix] = glGetUniformLocation(m_uProgram, kCCUniformPMatrix_s); + m_uUniforms[kCCUniformMVMatrix] = glGetUniformLocation(m_uProgram, kCCUniformMVMatrix_s); + m_uUniforms[kCCUniformMVPMatrix] = glGetUniformLocation(m_uProgram, kCCUniformMVPMatrix_s); + + m_uUniforms[kCCUniformTime] = glGetUniformLocation(m_uProgram, kCCUniformTime_s); + m_uUniforms[kCCUniformSinTime] = glGetUniformLocation(m_uProgram, kCCUniformSinTime_s); + m_uUniforms[kCCUniformCosTime] = glGetUniformLocation(m_uProgram, kCCUniformCosTime_s); + + m_bUsesTime = ( + m_uUniforms[kCCUniformTime] != -1 || + m_uUniforms[kCCUniformSinTime] != -1 || + m_uUniforms[kCCUniformCosTime] != -1 + ); + + m_uUniforms[kCCUniformRandom01] = glGetUniformLocation(m_uProgram, kCCUniformRandom01_s); m_uUniforms[kCCUniformSampler] = glGetUniformLocation(m_uProgram, kCCUniformSampler_s); this->use(); - this->setUniformLocationWith1i( m_uUniforms[kCCUniformSampler], 0 ); + + // Since sample most probably won't change, set it to 0 now. + this->setUniformLocationWith1i(m_uUniforms[kCCUniformSampler], 0); } bool CCGLProgram::link() { + CCAssert(m_uProgram != 0, "Cannot link invalid program"); + + GLint status = GL_TRUE; + glLinkProgram(m_uProgram); + if (m_uVertShader) + { + glDeleteShader(m_uVertShader); + } + + if (m_uFragShader) + { + glDeleteShader(m_uFragShader); + } + + m_uVertShader = m_uFragShader = 0; + #if DEBUG - GLint status; - glValidateProgram(m_uProgram); - glGetProgramiv(m_uProgram, GL_LINK_STATUS, &status); - if (status == GL_FALSE) { + + if (status == GL_FALSE) + { CCLOG("cocos2d: ERROR: Failed to link program: %i", m_uProgram); - if( m_uVertShader ) - glDeleteShader( m_uVertShader ); - if( m_uFragShader ) - glDeleteShader( m_uFragShader ); - ccGLDeleteProgram( m_uProgram ); - m_uVertShader = m_uFragShader = m_uProgram = 0; - return false; + ccGLDeleteProgram(m_uProgram); + m_uProgram = 0; } #endif - - if (m_uVertShader) - glDeleteShader(m_uVertShader); - if (m_uFragShader) - glDeleteShader(m_uFragShader); - - m_uVertShader = m_uFragShader = 0; - - return true; + + return (status == GL_TRUE); } void CCGLProgram::use() @@ -242,14 +296,19 @@ const char* CCGLProgram::programLog() // Uniform cache -bool CCGLProgram::updateUniformLocation(unsigned int location, GLvoid* data, unsigned int bytes) +bool CCGLProgram::updateUniformLocation(GLint location, GLvoid* data, unsigned int bytes) { + if (location < 0) + { + return false; + } + bool updated = true; tHashUniformEntry *element = NULL; HASH_FIND_INT(m_pHashForUniforms, &location, element); - if( ! element ) { - + if (! element) + { element = (tHashUniformEntry*)malloc( sizeof(*element) ); // key @@ -263,16 +322,20 @@ bool CCGLProgram::updateUniformLocation(unsigned int location, GLvoid* data, uns } else { - if( memcmp( element->value, data, bytes) == 0 ) + if (memcmp(element->value, data, bytes) == 0) + { updated = false; + } else - memcpy( element->value, data, bytes ); + { + memcpy(element->value, data, bytes); + } } return updated; } -void CCGLProgram::setUniformLocationWith1i(unsigned int location, GLint i1) +void CCGLProgram::setUniformLocationWith1i(GLint location, GLint i1) { bool updated = updateUniformLocation(location, &i1, sizeof(i1)*1); @@ -282,7 +345,7 @@ void CCGLProgram::setUniformLocationWith1i(unsigned int location, GLint i1) } } -void CCGLProgram::setUniformLocationWith1f(unsigned int location, GLfloat f1) +void CCGLProgram::setUniformLocationWith1f(GLint location, GLfloat f1) { bool updated = updateUniformLocation(location, &f1, sizeof(f1)*1); @@ -292,7 +355,7 @@ void CCGLProgram::setUniformLocationWith1f(unsigned int location, GLfloat f1) } } -void CCGLProgram::setUniformLocationWith2f(unsigned int location, GLfloat f1, GLfloat f2) +void CCGLProgram::setUniformLocationWith2f(GLint location, GLfloat f1, GLfloat f2) { GLfloat floats[2] = {f1,f2}; bool updated = updateUniformLocation(location, floats, sizeof(floats)); @@ -303,7 +366,7 @@ void CCGLProgram::setUniformLocationWith2f(unsigned int location, GLfloat f1, GL } } -void CCGLProgram::setUniformLocationWith3f(unsigned int location, GLfloat f1, GLfloat f2, GLfloat f3) +void CCGLProgram::setUniformLocationWith3f(GLint location, GLfloat f1, GLfloat f2, GLfloat f3) { GLfloat floats[3] = {f1,f2,f3}; bool updated = updateUniformLocation(location, floats, sizeof(floats)); @@ -314,7 +377,7 @@ void CCGLProgram::setUniformLocationWith3f(unsigned int location, GLfloat f1, GL } } -void CCGLProgram::setUniformLocationWith4f(unsigned int location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4) +void CCGLProgram::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)); @@ -325,7 +388,7 @@ void CCGLProgram::setUniformLocationWith4f(unsigned int location, GLfloat f1, GL } } -void CCGLProgram::setUniformLocationWith2fv(unsigned int location, GLfloat* floats, unsigned int numberOfArrays) +void CCGLProgram::setUniformLocationWith2fv(GLint location, GLfloat* floats, unsigned int numberOfArrays) { bool updated = updateUniformLocation(location, floats, sizeof(float)*2*numberOfArrays); @@ -335,7 +398,7 @@ void CCGLProgram::setUniformLocationWith2fv(unsigned int location, GLfloat* floa } } -void CCGLProgram::setUniformLocationWith3fv(unsigned int location, GLfloat* floats, unsigned int numberOfArrays) +void CCGLProgram::setUniformLocationWith3fv(GLint location, GLfloat* floats, unsigned int numberOfArrays) { bool updated = updateUniformLocation(location, floats, sizeof(float)*3*numberOfArrays); @@ -345,7 +408,7 @@ void CCGLProgram::setUniformLocationWith3fv(unsigned int location, GLfloat* floa } } -void CCGLProgram::setUniformLocationWith4fv(unsigned int location, GLfloat* floats, unsigned int numberOfArrays) +void CCGLProgram::setUniformLocationWith4fv(GLint location, GLfloat* floats, unsigned int numberOfArrays) { bool updated = updateUniformLocation(location, floats, sizeof(float)*4*numberOfArrays); @@ -356,7 +419,7 @@ void CCGLProgram::setUniformLocationWith4fv(unsigned int location, GLfloat* floa } -void CCGLProgram::setUniformLocationwithMatrix4fv(unsigned int location, GLfloat* matrixArray, unsigned int numberOfMatrices) +void CCGLProgram::setUniformLocationwithMatrix4fv(GLint location, GLfloat* matrixArray, unsigned int numberOfMatrices) { bool updated = updateUniformLocation(location, matrixArray, sizeof(float)*16*numberOfMatrices); @@ -366,18 +429,43 @@ void CCGLProgram::setUniformLocationwithMatrix4fv(unsigned int location, GLfloat } } -void CCGLProgram::setUniformForModelViewProjectionMatrix() +void CCGLProgram::setUniformsForBuiltins() { kmMat4 matrixP; - kmMat4 matrixMV; - kmMat4 matrixMVP; + kmMat4 matrixMV; + kmMat4 matrixMVP; + + kmGLGetMatrix(KM_GL_PROJECTION, &matrixP); + kmGLGetMatrix(KM_GL_MODELVIEW, &matrixMV); + + kmMat4Multiply(&matrixMVP, &matrixP, &matrixMV); + + setUniformLocationWith4fv(m_uUniforms[kCCUniformPMatrix], matrixP.mat, 1); + setUniformLocationWith4fv(m_uUniforms[kCCUniformMVMatrix], matrixMV.mat, 1); + setUniformLocationWith4fv(m_uUniforms[kCCUniformMVPMatrix], matrixMVP.mat, 1); + + if(m_bUsesTime) + { + CCDirector *director = CCDirector::sharedDirector(); + // This doesn't give the most accurate global time value. + // Cocos2D doesn't store a high precision time value, so this will have to do. + // Getting Mach time per frame per shader using time could be extremely expensive. + float time = director->getTotalFrames() * director->getAnimationInterval(); + + setUniformLocationWith4f(m_uUniforms[kCCUniformTime], time/10.0, time, time*2, time*4); + setUniformLocationWith4f(m_uUniforms[kCCUniformSinTime], time/8.0, time/4.0, time/2.0, sinf(time)); + setUniformLocationWith4f(m_uUniforms[kCCUniformCosTime], time/8.0, time/4.0, time/2.0, cosf(time)); + } + + if (m_uUniforms[kCCUniformRandom01] != -1) + { + setUniformLocationWith4f(m_uUniforms[kCCUniformRandom01], CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1()); + } +} - kmGLGetMatrix(KM_GL_PROJECTION, &matrixP ); - kmGLGetMatrix(KM_GL_MODELVIEW, &matrixMV ); - - kmMat4Multiply(&matrixMVP, &matrixP, &matrixMV); - - setUniformLocationwithMatrix4fv(m_uUniforms[kCCUniformMVPMatrix], matrixMVP.mat, 1); +void CCGLProgram::setUniformForModelViewProjectionMatrix() +{ + setUniformsForBuiltins(); } void CCGLProgram::reset() diff --git a/cocos2dx/shaders/CCGLProgram.h b/cocos2dx/shaders/CCGLProgram.h index ecb9ad5789..bfc5a943f0 100644 --- a/cocos2dx/shaders/CCGLProgram.h +++ b/cocos2dx/shaders/CCGLProgram.h @@ -49,24 +49,37 @@ enum { }; enum { - kCCUniformMVPMatrix, - kCCUniformSampler, - - kCCUniform_MAX, + kCCUniformPMatrix, + kCCUniformMVMatrix, + kCCUniformMVPMatrix, + kCCUniformTime, + kCCUniformSinTime, + kCCUniformCosTime, + kCCUniformRandom01, + kCCUniformSampler, + + kCCUniform_MAX, }; -#define kCCShader_PositionTextureColor "ShaderPositionTextureColor" -#define kCCShader_PositionTextureColorAlphaTest "ShaderPositionTextureColorAlphaTest" -#define kCCShader_PositionColor "ShaderPositionColor" -#define kCCShader_PositionTexture "ShaderPositionTexture" -#define kCCShader_PositionTexture_uColor "ShaderPositionTexture_uColor" -#define kCCShader_PositionTextureA8Color "ShaderPositionTextureA8Color" -#define kCCShader_Position_uColor "ShaderPosition_uColor" +#define kCCShader_PositionTextureColor "ShaderPositionTextureColor" +#define kCCShader_PositionTextureColorAlphaTest "ShaderPositionTextureColorAlphaTest" +#define kCCShader_PositionColor "ShaderPositionColor" +#define kCCShader_PositionTexture "ShaderPositionTexture" +#define kCCShader_PositionTexture_uColor "ShaderPositionTexture_uColor" +#define kCCShader_PositionTextureA8Color "ShaderPositionTextureA8Color" +#define kCCShader_Position_uColor "ShaderPosition_uColor" +#define kCCShader_PositionLengthTexureColor "ShaderPositionLengthTextureColor" // uniform names -#define kCCUniformMVPMatrix_s "u_MVPMatrix" -#define kCCUniformSampler_s "u_texture" -#define kCCUniformAlphaTestValue "u_alpha_value" +#define kCCUniformPMatrix_s "CC_PMatrix" +#define kCCUniformMVMatrix_s "CC_MVMatrix" +#define kCCUniformMVPMatrix_s "CC_MVPMatrix" +#define kCCUniformTime_s "CC_Time" +#define kCCUniformSinTime_s "CC_SinTime" +#define kCCUniformCosTime_s "CC_CosTime" +#define kCCUniformRandom01_s "CC_Random01" +#define kCCUniformSampler_s "CC_Texture0" +#define kCCUniformAlphaTestValue "CC_alpha_value" // Attribute names #define kCCAttributeNameColor "a_color" @@ -87,8 +100,6 @@ typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length, class CC_DLL CCGLProgram : public CCObject { public: - - CCGLProgram(); virtual ~CCGLProgram(); /** Initializes the CCGLProgram with a vertex and fragment with bytes array */ @@ -101,9 +112,10 @@ public: bool link(); /** it will call glUseProgram() */ void use(); -/** It will create 3 uniforms: +/** It will create 4 uniforms: - kCCUniformPMatrix - kCCUniformMVMatrix + - kCCUniformMVPMatrix - kCCUniformSampler And it will bind "kCCUniformSampler" to 0 @@ -111,34 +123,37 @@ public: */ void updateUniforms(); /** calls glUniform1i only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith1i(unsigned int location, GLint i1); + void setUniformLocationWith1i(GLint location, GLint i1); /** calls glUniform1f only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith1f(unsigned int location, GLfloat f1); + void setUniformLocationWith1f(GLint location, GLfloat f1); /** calls glUniform2f only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith2f(unsigned int location, GLfloat f1, GLfloat f2); + void setUniformLocationWith2f(GLint location, GLfloat f1, GLfloat f2); /** calls glUniform3f only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith3f(unsigned int location, GLfloat f1, GLfloat f2, GLfloat f3); + void setUniformLocationWith3f(GLint location, GLfloat f1, GLfloat f2, GLfloat f3); /** calls glUniform4f only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith4f(unsigned int location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4); + void setUniformLocationWith4f(GLint location, GLfloat f1, GLfloat f2, GLfloat f3, GLfloat f4); /** calls glUniform2fv only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith2fv(unsigned int location, GLfloat* floats, unsigned int numberOfArrays); + void setUniformLocationWith2fv(GLint location, GLfloat* floats, unsigned int numberOfArrays); /** calls glUniform3fv only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith3fv(unsigned int location, GLfloat* floats, unsigned int numberOfArrays); + void setUniformLocationWith3fv(GLint location, GLfloat* floats, unsigned int numberOfArrays); /** calls glUniform4fv only if the values are different than the previous call for this same shader program. */ - void setUniformLocationWith4fv(unsigned int location, GLfloat* floats, unsigned int numberOfArrays); + void setUniformLocationWith4fv(GLint location, GLfloat* floats, unsigned int numberOfArrays); /** calls glUniformMatrix4fv only if the values are different than the previous call for this same shader program. */ - void setUniformLocationwithMatrix4fv(unsigned int location, GLfloat* matrixArray, unsigned int numberOfMatrices); + void setUniformLocationwithMatrix4fv(GLint location, GLfloat* matrixArray, unsigned int numberOfMatrices); + + /** will update the builtin uniforms if they are different than the previous call for this same shader program. */ + void setUniformsForBuiltins(); - /** will update the MVP matrix on the MVP uniform if it is different than the previous call for this same shader program. */ - void setUniformForModelViewProjectionMatrix(); + /** Deprecated alias for setUniformsForBuiltins */ + CC_DEPRECATED_ATTRIBUTE void setUniformForModelViewProjectionMatrix(); /** returns the vertexShader error log */ const char* vertexShaderLog(); @@ -154,7 +169,7 @@ public: inline const GLuint getProgram() { return m_uProgram; } private: - bool updateUniformLocation(unsigned int location, GLvoid* data, unsigned int bytes); + bool updateUniformLocation(GLint location, GLvoid* data, unsigned int bytes); const char* description(); bool compileShader(GLuint * shader, GLenum type, const GLchar* source); const char* logForOpenGLObject(GLuint object, GLInfoFunction infoFunc, GLLogFunction logFunc); @@ -163,8 +178,9 @@ private: GLuint m_uProgram; GLuint m_uVertShader; GLuint m_uFragShader; - GLint m_uUniforms[kCCUniform_MAX]; + GLint m_uUniforms[kCCUniform_MAX]; struct _hashUniformEntry* m_pHashForUniforms; + bool m_bUsesTime; }; // end of shaders group diff --git a/cocos2dx/shaders/ccGLStateCache.cpp b/cocos2dx/shaders/ccGLStateCache.cpp index e27a07ace3..e09fc94c83 100644 --- a/cocos2dx/shaders/ccGLStateCache.cpp +++ b/cocos2dx/shaders/ccGLStateCache.cpp @@ -47,11 +47,10 @@ static bool s_bVertexAttribTexCoords = false; static GLuint s_uCurrentShaderProgram = -1; static GLuint s_uCurrentBoundTexture[kCCMaxActiveTexture] = {(GLuint)-1,(GLuint)-1,(GLuint)-1,(GLuint)-1, (GLuint)-1,(GLuint)-1,(GLuint)-1,(GLuint)-1, (GLuint)-1,(GLuint)-1,(GLuint)-1,(GLuint)-1, (GLuint)-1,(GLuint)-1,(GLuint)-1,(GLuint)-1, }; -static GLenum s_eCurrentActiveTexture = (GL_TEXTURE0 - GL_TEXTURE0); static GLenum s_eBlendingSource = -1; static GLenum s_eBlendingDest = -1; static int s_eGLServerState = 0; - +static GLuint s_uVAO = 0; #endif // CC_ENABLE_GL_STATE_CACHE // GL State Cache functions @@ -69,7 +68,7 @@ void ccGLInvalidateStateCache( void ) { s_uCurrentBoundTexture[i] = -1; } - s_eCurrentActiveTexture = (GL_TEXTURE0 - GL_TEXTURE0); + s_eBlendingSource = -1; s_eBlendingDest = -1; s_eGLServerState = 0; @@ -98,89 +97,112 @@ void ccGLUseProgram( GLuint program ) #endif // CC_ENABLE_GL_STATE_CACHE } +static void SetBlending(GLenum sfactor, GLenum dfactor) +{ + if (sfactor == GL_ONE && dfactor == GL_ZERO) + { + glDisable(GL_BLEND); + } + else + { + glEnable(GL_BLEND); + glBlendFunc(sfactor, dfactor); + } +} void ccGLBlendFunc(GLenum sfactor, GLenum dfactor) { #if CC_ENABLE_GL_STATE_CACHE - if( sfactor != s_eBlendingSource || dfactor != s_eBlendingDest ) { + if (sfactor != s_eBlendingSource || dfactor != s_eBlendingDest) + { s_eBlendingSource = sfactor; s_eBlendingDest = dfactor; - glBlendFunc( sfactor, dfactor ); + SetBlending(sfactor, dfactor); } #else - glBlendFunc( sfactor, dfactor ); + SetBlending( sfactor, dfactor ); #endif // CC_ENABLE_GL_STATE_CACHE } -GLenum ccGLGetActiveTexture( void ) +void ccGLBlendResetToCache(void) { + glBlendEquation(GL_FUNC_ADD); #if CC_ENABLE_GL_STATE_CACHE - return s_eCurrentActiveTexture + GL_TEXTURE0; + SetBlending(s_eBlendingSource, s_eBlendingDest); #else - GLenum activeTexture; - glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&activeTexture); - return activeTexture; -#endif + SetBlending(CC_BLEND_SRC, CC_BLEND_DST); +#endif // CC_ENABLE_GL_STATE_CACHE } -void ccGLActiveTexture( GLenum textureEnum ) +void ccGLBindTexture2DN(GLuint textureUnit, GLuint textureId) { #if CC_ENABLE_GL_STATE_CACHE - CCAssert( (textureEnum - GL_TEXTURE0) < kCCMaxActiveTexture, "cocos2d ERROR: Increase kCCMaxActiveTexture to kCCMaxActiveTexture!"); - if( (textureEnum - GL_TEXTURE0) != s_eCurrentActiveTexture ) { - s_eCurrentActiveTexture = (textureEnum - GL_TEXTURE0); - glActiveTexture( textureEnum ); - } -#else - glActiveTexture( textureEnum ); -#endif -} - -void ccGLBindTexture2D( GLuint textureId ) -{ -#if CC_ENABLE_GL_STATE_CACHE - if( s_uCurrentBoundTexture[ s_eCurrentActiveTexture ] != textureId ) + CCAssert(textureUnit < kCCMaxActiveTexture, "textureUnit is too big"); + if( s_uCurrentBoundTexture[textureUnit] != textureId ) { - s_uCurrentBoundTexture[ s_eCurrentActiveTexture ] = textureId; + s_uCurrentBoundTexture[textureUnit] = textureId; + glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, textureId ); } #else + glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, textureId ); #endif } void ccGLDeleteTexture( GLuint textureId ) +{ + ccGLDeleteTextureN(0, textureId); +} + +void ccGLDeleteTextureN(GLuint textureUnit, GLuint textureId) { #if CC_ENABLE_GL_STATE_CACHE - if( textureId == s_uCurrentBoundTexture[ s_eCurrentActiveTexture ] ) - s_uCurrentBoundTexture[ s_eCurrentActiveTexture ] = -1; + if (s_uCurrentBoundTexture[textureUnit] == textureId) + { + s_uCurrentBoundTexture[textureUnit] = -1; + } +#endif // CC_ENABLE_GL_STATE_CACHE + + glDeleteTextures(1, &textureId ); +} + +void ccGLBindVAO(GLuint vaoId) +{ +#if CC_ENABLE_GL_STATE_CACHE + if (s_uVAO != vaoId) + { + s_uVAO = vaoId; + glBindVertexArray(vaoId); + } +#else + glBindVertexArray(vaoId); #endif - glDeleteTextures(1, &textureId ); } void ccGLEnable( ccGLServerState flags ) { #if CC_ENABLE_GL_STATE_CACHE - int enabled = 0; - - /* GL_BLEND */ - if( (enabled = (flags & CC_GL_BLEND)) != (s_eGLServerState & CC_GL_BLEND) ) { - if( enabled ) { - glEnable( GL_BLEND ); - s_eGLServerState |= CC_GL_BLEND; - } else { - glDisable( GL_BLEND ); - s_eGLServerState &= ~CC_GL_BLEND; - } - } +// int enabled = 0; +// +// /* GL_BLEND */ +// if( (enabled = (flags & CC_GL_BLEND)) != (s_eGLServerState & CC_GL_BLEND) ) { +// if( enabled ) { +// glEnable( GL_BLEND ); +// s_eGLServerState |= CC_GL_BLEND; +// } else { +// glDisable( GL_BLEND ); +// s_eGLServerState &= ~CC_GL_BLEND; +// } +// } #else - if( flags & CC_GL_BLEND ) - glEnable( GL_BLEND ); - else - glDisable( GL_BLEND ); +// if( flags & CC_GL_BLEND ) +// glEnable( GL_BLEND ); +// else +// glDisable( GL_BLEND ); #endif } @@ -188,6 +210,8 @@ void ccGLEnable( ccGLServerState flags ) void ccGLEnableVertexAttribs( unsigned int flags ) { + ccGLBindVAO(0); + /* Position */ bool enablePosition = flags & kCCVertexAttribFlag_Position; diff --git a/cocos2dx/shaders/ccGLStateCache.h b/cocos2dx/shaders/ccGLStateCache.h index 3d4f31afd4..6cd79d68ea 100644 --- a/cocos2dx/shaders/ccGLStateCache.h +++ b/cocos2dx/shaders/ccGLStateCache.h @@ -55,11 +55,12 @@ typedef enum { // CC_GL_SCISSOR_TEST = 1 << 0, // CC_GL_STENCIL_TEST = 1 << 1, // CC_GL_DEPTH_TEST = 1 << 2, - CC_GL_BLEND = 1 << 3, +// CC_GL_BLEND = 1 << 3, // CC_GL_DITHER = 1 << 4, // CC_GL_ALL = ( CC_GL_SCISSOR_TEST | CC_GL_STENCIL_TEST | CC_GL_DEPTH_TEST | CC_GL_BLEND | CC_GL_DITHER ), - CC_GL_ALL = ( CC_GL_BLEND ), +// CC_GL_ALL = ( CC_GL_BLEND ), + CC_GL_ALL = 0, } ccGLServerState; @@ -70,19 +71,19 @@ typedef enum { If CC_ENABLE_GL_STATE_CACHE it will reset the GL state cache. @since v2.0.0 */ -void CC_DLL ccGLInvalidateStateCache( void ); +void CC_DLL ccGLInvalidateStateCache(void); /** Uses the GL program in case program is different than the current one. If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glUseProgram() directly. @since v2.0.0 */ -void CC_DLL ccGLUseProgram( GLuint program ); +void CC_DLL ccGLUseProgram(GLuint program); /** Deletes the GL program. If it is the one that is being used, it invalidates it. If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glDeleteProgram() directly. @since v2.0.0 */ -void CC_DLL ccGLDeleteProgram( GLuint program ); +void CC_DLL ccGLDeleteProgram(GLuint program); /** Uses a blending function in case it not already used. If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glBlendFunc() directly. @@ -90,10 +91,16 @@ void CC_DLL ccGLDeleteProgram( GLuint program ); */ void CC_DLL ccGLBlendFunc(GLenum sfactor, GLenum dfactor); +/** Resets the blending mode back to the cached state in case you used glBlendFuncSeparate() or glBlendEquation(). + If CC_ENABLE_GL_STATE_CACHE is disabled, it will just set the default blending mode using GL_FUNC_ADD. + @since v2.0.0 + */ +void ccGLBlendResetToCache(void); + /** sets the projection matrix as dirty @since v2.0.0 */ -void CC_DLL ccSetProjectionMatrixDirty( void ); +void CC_DLL ccSetProjectionMatrixDirty(void); /** Will enable the vertex attribs that are passed as flags. Possible flags: @@ -106,26 +113,20 @@ void CC_DLL ccSetProjectionMatrixDirty( void ); @since v2.0.0 */ -void CC_DLL ccGLEnableVertexAttribs( unsigned int flags ); +void CC_DLL ccGLEnableVertexAttribs(unsigned int flags); -/** If the active texture is not textureEnum, then it will active it. - If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glActiveTexture() directly. - @since v2.0.0 +/** If the texture is not already bound to texture unit 0, it binds it. + If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. + @since v2.1.0 */ -void CC_DLL ccGLActiveTexture(GLenum textureEnum ); - -/** Returns the active texture. - If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glGetIntegerv(GL_ACTIVE_TEXTURE); - @since v2.0.0 - */ -GLenum CC_DLL ccGLGetActiveTexture( void ); +void ccGLBindTexture2D(GLuint textureId); -/** If the texture is not already bound, it binds it. +/** If the texture is not already bound to a given unit, it binds it. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly. @since v2.0.0 */ -void CC_DLL ccGLBindTexture2D(GLuint textureId ); +void CC_DLL ccGLBindTexture2DN(GLuint textureUnit, GLuint textureId); /** It will delete a given texture. If the texture was bound, it will invalidate the cached. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. @@ -133,6 +134,18 @@ void CC_DLL ccGLBindTexture2D(GLuint textureId ); */ void CC_DLL ccGLDeleteTexture(GLuint textureId); +/** It will delete a given texture. If the texture was bound, it will invalidate the cached for the given texture unit. + If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glDeleteTextures() directly. + @since v2.1.0 + */ +void ccGLDeleteTextureN(GLuint textureUnit, GLuint textureId); + +/** If the vertex array is not already bound, it binds it. + If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindVertexArray() directly. + @since v2.0.0 + */ +void ccGLBindVAO(GLuint vaoId); + /** It will enable / disable the server side GL states. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glEnable() directly. @since v2.0.0 diff --git a/cocos2dx/textures/CCTexture2D.cpp b/cocos2dx/textures/CCTexture2D.cpp index 637a6f93de..008a650b85 100644 --- a/cocos2dx/textures/CCTexture2D.cpp +++ b/cocos2dx/textures/CCTexture2D.cpp @@ -480,7 +480,7 @@ void CCTexture2D::drawAtPoint(const CCPoint& point) ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); m_pShaderProgram->use(); - m_pShaderProgram->setUniformForModelViewProjectionMatrix(); + m_pShaderProgram->setUniformsForBuiltins(); ccGLBindTexture2D( m_uName ); @@ -506,7 +506,7 @@ void CCTexture2D::drawInRect(const CCRect& rect) ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); m_pShaderProgram->use(); - m_pShaderProgram->setUniformForModelViewProjectionMatrix(); + m_pShaderProgram->setUniformsForBuiltins(); ccGLBindTexture2D( m_uName );