issue #1555:add CCDrawNode

This commit is contained in:
minggo 2012-11-09 12:08:18 +08:00
parent 6159a8b592
commit d2a5723973
18 changed files with 609 additions and 190 deletions

View File

@ -403,7 +403,6 @@ void CCDirector::setAlphaBlending(bool bOn)
{ {
if (bOn) if (bOn)
{ {
ccGLEnable(CC_GL_BLEND);
ccGLBlendFunc(CC_BLEND_SRC, CC_BLEND_DST); ccGLBlendFunc(CC_BLEND_SRC, CC_BLEND_DST);
} }
else else

View File

@ -82,7 +82,7 @@ CCNode::CCNode(void)
, m_nScriptHandler(0) , m_nScriptHandler(0)
, m_pShaderProgram(NULL) , m_pShaderProgram(NULL)
, m_nOrderOfArrival(0) , m_nOrderOfArrival(0)
, m_glServerState(CC_GL_BLEND) , m_glServerState(ccGLServerState(0))
, m_bReorderChildDirty(false) , m_bReorderChildDirty(false)
{ {
// set default scheduler and actionManager // set default scheduler and actionManager
@ -537,9 +537,9 @@ void CCNode::addChild(CCNode *child)
this->addChild(child, child->m_nZOrder, child->m_nTag); this->addChild(child, child->m_nZOrder, child->m_nTag);
} }
void CCNode::removeFromParent() void CCNode::removeFromParent()
{ {
this->removeFromParentAndCleanup(true); this->removeFromParentAndCleanup(true);
} }
void CCNode::removeFromParentAndCleanup(bool cleanup) void CCNode::removeFromParentAndCleanup(bool cleanup)
@ -1144,11 +1144,11 @@ CCPoint CCNode::convertTouchToNodeSpaceAR(CCTouch *touch)
return this->convertToNodeSpaceAR(point); return this->convertToNodeSpaceAR(point);
} }
// MARMALADE ADDED // MARMALADE ADDED
void CCNode::updateTransform() void CCNode::updateTransform()
{ {
// Recursively iterate over children // Recursively iterate over children
arrayMakeObjectsPerformSelector(m_pChildren, updateTransform, CCNode*); arrayMakeObjectsPerformSelector(m_pChildren, updateTransform, CCNode*);
} }
NS_CC_END NS_CC_END

View File

@ -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

View File

@ -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__

View File

@ -83,7 +83,7 @@ void ccDrawPoint( const CCPoint& point )
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize); s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize);
@ -101,7 +101,7 @@ void ccDrawPoints( const CCPoint *points, unsigned int numberOfPoints )
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize); s_pShader->setUniformLocationWith1f(s_nPointSizeLocation, s_fPointSize);
@ -142,7 +142,7 @@ void ccDrawLine( const CCPoint& origin, const CCPoint& destination )
s_pShader->use(); s_pShader->use();
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
@ -181,7 +181,7 @@ void ccDrawPoly( const CCPoint *poli, unsigned int numberOfPoints, bool closePol
lazy_init(); lazy_init();
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
@ -223,7 +223,7 @@ void ccDrawSolidPoly( const CCPoint *poli, unsigned int numberOfPoints, ccColor4
lazy_init(); lazy_init();
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &color.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &color.r, 1);
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); 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; vertices[(segments+1)*2+1] = center.y;
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
@ -313,7 +313,7 @@ void ccDrawQuadBezier(const CCPoint& origin, const CCPoint& control, const CCPoi
vertices[segments].y = destination.y; vertices[segments].y = destination.y;
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
@ -365,7 +365,7 @@ void ccDrawCardinalSpline( CCPointArray *config, float tension, unsigned int se
} }
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*)&s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*)&s_tColor.r, 1);
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
@ -394,7 +394,7 @@ void ccDrawCubicBezier(const CCPoint& origin, const CCPoint& control1, const CCP
vertices[segments].y = destination.y; vertices[segments].y = destination.y;
s_pShader->use(); s_pShader->use();
s_pShader->setUniformForModelViewProjectionMatrix(); s_pShader->setUniformsForBuiltins();
s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1); s_pShader->setUniformLocationWith4fv(s_nColorLocation, (GLfloat*) &s_tColor.r, 1);
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );

View File

@ -337,7 +337,7 @@ void CCGrid3D::blit(void)
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
m_pShaderProgram->use(); m_pShaderProgram->use();
m_pShaderProgram->setUniformForModelViewProjectionMatrix();; m_pShaderProgram->setUniformsForBuiltins();;
// //
// Attributes // Attributes
@ -542,7 +542,7 @@ void CCTiledGrid3D::blit(void)
m_pShaderProgram->use(); m_pShaderProgram->use();
m_pShaderProgram->setUniformForModelViewProjectionMatrix(); m_pShaderProgram->setUniformsForBuiltins();
// //
// Attributes // Attributes

View File

@ -88,7 +88,7 @@ do { \
CCAssert(getShaderProgram(), "No shader program set for this node"); \ CCAssert(getShaderProgram(), "No shader program set for this node"); \
{ \ { \
getShaderProgram()->use(); \ getShaderProgram()->use(); \
getShaderProgram()->setUniformForModelViewProjectionMatrix(); \ getShaderProgram()->setUniformsForBuiltins(); \
} \ } \
} while(0) } while(0)

View File

@ -69,6 +69,9 @@ THE SOFTWARE.
#include "cocoa/CCNS.h" #include "cocoa/CCNS.h"
#include "cocoa/CCZone.h" #include "cocoa/CCZone.h"
// draw nodes
#include "draw_nodes/CCDrawingPrimitives.h"
// effects // effects
#include "effects/CCGrabber.h" #include "effects/CCGrabber.h"
#include "effects/CCGrid.h" #include "effects/CCGrid.h"

View File

@ -242,7 +242,7 @@ void CCLayer::setAccelerometerInterval(double interval) {
{ {
if (m_bIsRunning) if (m_bIsRunning)
{ {
CCDirector* pDirector = CCDirector::sharedDirector(); // CCDirector* pDirector = CCDirector::sharedDirector();
// pDirector->getAccelerometer()->setAccelerometerInterval(interval); // pDirector->getAccelerometer()->setAccelerometerInterval(interval);
} }
} }

View File

@ -30,6 +30,8 @@
#include "shaders/CCGLProgram.h" #include "shaders/CCGLProgram.h"
#include "shaders/CCShaderCache.h" #include "shaders/CCShaderCache.h"
#include "CCDirector.h" #include "CCDirector.h"
#include "support/CCPointExtension.h"
#include "draw_nodes/CCDrawingPrimitives.h"
NS_CC_BEGIN NS_CC_BEGIN
@ -358,4 +360,36 @@ void CCClippingNode::visit()
layer--; 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 NS_CC_END

View File

@ -76,7 +76,7 @@ public:
The stencil node will be retained. The stencil node will be retained.
This default to nil. This default to nil.
*/ */
CCNode* getStencil(); CCNode* getStencil() const;
void setStencil(CCNode *pStencil); void setStencil(CCNode *pStencil);
/** The alpha threshold. /** The alpha threshold.
@ -84,15 +84,15 @@ public:
Should be a float between 0 and 1. Should be a float between 0 and 1.
This default to 1 (so alpha test is disabled). This default to 1 (so alpha test is disabled).
*/ */
GLfloat getAlphaThreshold(); GLfloat getAlphaThreshold() const;
void setAlphaThreshold(GLfloat fAlphaThreshold); void setAlphaThreshold(GLfloat fAlphaThreshold);
/** Inverted. If this is set to YES, /** Inverted. If this is set to YES,
the stencil is inverted, so the content is drawn where the stencil is NOT drawn. the stencil is inverted, so the content is drawn where the stencil is NOT drawn.
This default to NO. This default to NO.
*/ */
bool isInverted(); bool isInverted() const;
bool setInverted(bool bInverted); void setInverted(bool bInverted);
private: private:
CCClippingNode(); CCClippingNode();

View File

@ -1 +1 @@
a63972a39f79cdc3fd02e88518f0e17da54554ae 2ca5fe7b3dd190dca76cc6d572d7c910f560e9ff

View File

@ -25,6 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
****************************************************************************/ ****************************************************************************/
#include "CCDirector.h"
#include "CCGLProgram.h" #include "CCGLProgram.h"
#include "ccGLStateCache.h" #include "ccGLStateCache.h"
#include "ccMacros.h" #include "ccMacros.h"
@ -58,8 +59,8 @@ CCGLProgram::~CCGLProgram()
CCLOGINFO("cocos2d: %s %d deallocing 0x%X", __FUNCTION__, __LINE__, this); CCLOGINFO("cocos2d: %s %d deallocing 0x%X", __FUNCTION__, __LINE__, this);
// there is no need to delete the shaders. They should have been already deleted. // 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_uVertShader == 0, "Vertex Shaders should have been already deleted");
CCAssert( m_uFragShader == 0, "Vertex Shaders should have been already deleted"); CCAssert(m_uFragShader == 0, "Fragment Shaders should have been already deleted");
if (m_uProgram) if (m_uProgram)
{ {
@ -69,7 +70,8 @@ CCGLProgram::~CCGLProgram()
tHashUniformEntry *current_element, *tmp; tHashUniformEntry *current_element, *tmp;
// Purge uniform hash // 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); HASH_DEL(m_pHashForUniforms, current_element);
free(current_element->value); free(current_element->value);
free(current_element); free(current_element);
@ -83,28 +85,34 @@ bool CCGLProgram::initWithVertexShaderByteArray(const GLchar* vShaderByteArray,
m_uVertShader = m_uFragShader = 0; 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"); CCLOG("cocos2d: ERROR: Failed to compile vertex shader");
} }
} }
// Create and compile fragment 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"); CCLOG("cocos2d: ERROR: Failed to compile fragment shader");
} }
} }
if( m_uVertShader ) { if (m_uVertShader)
{
glAttachShader(m_uProgram, m_uVertShader); glAttachShader(m_uProgram, m_uVertShader);
} }
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
if( m_uFragShader ) { if (m_uFragShader)
{
glAttachShader(m_uProgram, m_uFragShader); glAttachShader(m_uProgram, m_uFragShader);
} }
m_pHashForUniforms = NULL; m_pHashForUniforms = NULL;
@ -132,10 +140,27 @@ bool CCGLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* sour
GLint status; GLint status;
if (!source) if (!source)
{
return false; 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); *shader = glCreateShader(type);
glShaderSource(*shader, 1, &source, NULL); glShaderSource(*shader, sizeof(sources)/sizeof(*sources), sources, NULL);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
glCompileShader(*shader); glCompileShader(*shader);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
@ -143,64 +168,93 @@ bool CCGLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* sour
glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
CHECK_GL_ERROR_DEBUG(); CHECK_GL_ERROR_DEBUG();
if( ! status ) { if (! status)
if( type == GL_VERTEX_SHADER ) {
CCLOG("cocos2d: %s", vertexShaderLog() ); 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 else
CCLOG("cocos2d: %s", fragmentShaderLog() ); {
CCLOG("cocos2d: %s", fragmentShaderLog());
}
abort();
} }
return ( status == GL_TRUE ); return ( status == GL_TRUE );
} }
void CCGLProgram::addAttribute(const char* attributeName, GLuint index) void CCGLProgram::addAttribute(const char* attributeName, GLuint index)
{ {
glBindAttribLocation(m_uProgram, glBindAttribLocation(m_uProgram, index, attributeName);
index,
attributeName);
} }
void CCGLProgram::updateUniforms() void CCGLProgram::updateUniforms()
{ {
// Since sample most probably won't change, set it to 0 now. 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[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); m_uUniforms[kCCUniformSampler] = glGetUniformLocation(m_uProgram, kCCUniformSampler_s);
this->use(); 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() bool CCGLProgram::link()
{ {
CCAssert(m_uProgram != 0, "Cannot link invalid program");
GLint status = GL_TRUE;
glLinkProgram(m_uProgram); glLinkProgram(m_uProgram);
if (m_uVertShader)
{
glDeleteShader(m_uVertShader);
}
if (m_uFragShader)
{
glDeleteShader(m_uFragShader);
}
m_uVertShader = m_uFragShader = 0;
#if DEBUG #if DEBUG
GLint status;
glValidateProgram(m_uProgram);
glGetProgramiv(m_uProgram, GL_LINK_STATUS, &status); 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); CCLOG("cocos2d: ERROR: Failed to link program: %i", m_uProgram);
if( m_uVertShader ) ccGLDeleteProgram(m_uProgram);
glDeleteShader( m_uVertShader ); m_uProgram = 0;
if( m_uFragShader )
glDeleteShader( m_uFragShader );
ccGLDeleteProgram( m_uProgram );
m_uVertShader = m_uFragShader = m_uProgram = 0;
return false;
} }
#endif #endif
if (m_uVertShader) return (status == GL_TRUE);
glDeleteShader(m_uVertShader);
if (m_uFragShader)
glDeleteShader(m_uFragShader);
m_uVertShader = m_uFragShader = 0;
return true;
} }
void CCGLProgram::use() void CCGLProgram::use()
@ -242,14 +296,19 @@ const char* CCGLProgram::programLog()
// Uniform cache // 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; bool updated = true;
tHashUniformEntry *element = NULL; tHashUniformEntry *element = NULL;
HASH_FIND_INT(m_pHashForUniforms, &location, element); HASH_FIND_INT(m_pHashForUniforms, &location, element);
if( ! element ) { if (! element)
{
element = (tHashUniformEntry*)malloc( sizeof(*element) ); element = (tHashUniformEntry*)malloc( sizeof(*element) );
// key // key
@ -263,16 +322,20 @@ bool CCGLProgram::updateUniformLocation(unsigned int location, GLvoid* data, uns
} }
else else
{ {
if( memcmp( element->value, data, bytes) == 0 ) if (memcmp(element->value, data, bytes) == 0)
{
updated = false; updated = false;
}
else else
memcpy( element->value, data, bytes ); {
memcpy(element->value, data, bytes);
}
} }
return updated; 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); 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); 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}; GLfloat floats[2] = {f1,f2};
bool updated = updateUniformLocation(location, floats, sizeof(floats)); 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}; GLfloat floats[3] = {f1,f2,f3};
bool updated = updateUniformLocation(location, floats, sizeof(floats)); 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}; GLfloat floats[4] = {f1,f2,f3,f4};
bool updated = updateUniformLocation(location, floats, sizeof(floats)); 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); 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); 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); 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); 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 matrixP;
kmMat4 matrixMV; kmMat4 matrixMV;
kmMat4 matrixMVP; 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 ); void CCGLProgram::setUniformForModelViewProjectionMatrix()
kmGLGetMatrix(KM_GL_MODELVIEW, &matrixMV ); {
setUniformsForBuiltins();
kmMat4Multiply(&matrixMVP, &matrixP, &matrixMV);
setUniformLocationwithMatrix4fv(m_uUniforms[kCCUniformMVPMatrix], matrixMVP.mat, 1);
} }
void CCGLProgram::reset() void CCGLProgram::reset()

View File

@ -49,24 +49,37 @@ enum {
}; };
enum { enum {
kCCUniformMVPMatrix, kCCUniformPMatrix,
kCCUniformSampler, kCCUniformMVMatrix,
kCCUniformMVPMatrix,
kCCUniform_MAX, kCCUniformTime,
kCCUniformSinTime,
kCCUniformCosTime,
kCCUniformRandom01,
kCCUniformSampler,
kCCUniform_MAX,
}; };
#define kCCShader_PositionTextureColor "ShaderPositionTextureColor" #define kCCShader_PositionTextureColor "ShaderPositionTextureColor"
#define kCCShader_PositionTextureColorAlphaTest "ShaderPositionTextureColorAlphaTest" #define kCCShader_PositionTextureColorAlphaTest "ShaderPositionTextureColorAlphaTest"
#define kCCShader_PositionColor "ShaderPositionColor" #define kCCShader_PositionColor "ShaderPositionColor"
#define kCCShader_PositionTexture "ShaderPositionTexture" #define kCCShader_PositionTexture "ShaderPositionTexture"
#define kCCShader_PositionTexture_uColor "ShaderPositionTexture_uColor" #define kCCShader_PositionTexture_uColor "ShaderPositionTexture_uColor"
#define kCCShader_PositionTextureA8Color "ShaderPositionTextureA8Color" #define kCCShader_PositionTextureA8Color "ShaderPositionTextureA8Color"
#define kCCShader_Position_uColor "ShaderPosition_uColor" #define kCCShader_Position_uColor "ShaderPosition_uColor"
#define kCCShader_PositionLengthTexureColor "ShaderPositionLengthTextureColor"
// uniform names // uniform names
#define kCCUniformMVPMatrix_s "u_MVPMatrix" #define kCCUniformPMatrix_s "CC_PMatrix"
#define kCCUniformSampler_s "u_texture" #define kCCUniformMVMatrix_s "CC_MVMatrix"
#define kCCUniformAlphaTestValue "u_alpha_value" #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 // Attribute names
#define kCCAttributeNameColor "a_color" #define kCCAttributeNameColor "a_color"
@ -87,8 +100,6 @@ typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length,
class CC_DLL CCGLProgram : public CCObject class CC_DLL CCGLProgram : public CCObject
{ {
public: public:
CCGLProgram(); CCGLProgram();
virtual ~CCGLProgram(); virtual ~CCGLProgram();
/** Initializes the CCGLProgram with a vertex and fragment with bytes array */ /** Initializes the CCGLProgram with a vertex and fragment with bytes array */
@ -101,9 +112,10 @@ public:
bool link(); bool link();
/** it will call glUseProgram() */ /** it will call glUseProgram() */
void use(); void use();
/** It will create 3 uniforms: /** It will create 4 uniforms:
- kCCUniformPMatrix - kCCUniformPMatrix
- kCCUniformMVMatrix - kCCUniformMVMatrix
- kCCUniformMVPMatrix
- kCCUniformSampler - kCCUniformSampler
And it will bind "kCCUniformSampler" to 0 And it will bind "kCCUniformSampler" to 0
@ -111,34 +123,37 @@ public:
*/ */
void updateUniforms(); void updateUniforms();
/** calls glUniform1i only if the values are different than the previous call for this same shader program. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** 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. */ /** Deprecated alias for setUniformsForBuiltins */
void setUniformForModelViewProjectionMatrix(); CC_DEPRECATED_ATTRIBUTE void setUniformForModelViewProjectionMatrix();
/** returns the vertexShader error log */ /** returns the vertexShader error log */
const char* vertexShaderLog(); const char* vertexShaderLog();
@ -154,7 +169,7 @@ public:
inline const GLuint getProgram() { return m_uProgram; } inline const GLuint getProgram() { return m_uProgram; }
private: private:
bool updateUniformLocation(unsigned int location, GLvoid* data, unsigned int bytes); bool updateUniformLocation(GLint location, GLvoid* data, unsigned int bytes);
const char* description(); const char* description();
bool compileShader(GLuint * shader, GLenum type, const GLchar* source); bool compileShader(GLuint * shader, GLenum type, const GLchar* source);
const char* logForOpenGLObject(GLuint object, GLInfoFunction infoFunc, GLLogFunction logFunc); const char* logForOpenGLObject(GLuint object, GLInfoFunction infoFunc, GLLogFunction logFunc);
@ -163,8 +178,9 @@ private:
GLuint m_uProgram; GLuint m_uProgram;
GLuint m_uVertShader; GLuint m_uVertShader;
GLuint m_uFragShader; GLuint m_uFragShader;
GLint m_uUniforms[kCCUniform_MAX]; GLint m_uUniforms[kCCUniform_MAX];
struct _hashUniformEntry* m_pHashForUniforms; struct _hashUniformEntry* m_pHashForUniforms;
bool m_bUsesTime;
}; };
// end of shaders group // end of shaders group

View File

@ -47,11 +47,10 @@ static bool s_bVertexAttribTexCoords = false;
static GLuint s_uCurrentShaderProgram = -1; 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 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_eBlendingSource = -1;
static GLenum s_eBlendingDest = -1; static GLenum s_eBlendingDest = -1;
static int s_eGLServerState = 0; static int s_eGLServerState = 0;
static GLuint s_uVAO = 0;
#endif // CC_ENABLE_GL_STATE_CACHE #endif // CC_ENABLE_GL_STATE_CACHE
// GL State Cache functions // GL State Cache functions
@ -69,7 +68,7 @@ void ccGLInvalidateStateCache( void )
{ {
s_uCurrentBoundTexture[i] = -1; s_uCurrentBoundTexture[i] = -1;
} }
s_eCurrentActiveTexture = (GL_TEXTURE0 - GL_TEXTURE0);
s_eBlendingSource = -1; s_eBlendingSource = -1;
s_eBlendingDest = -1; s_eBlendingDest = -1;
s_eGLServerState = 0; s_eGLServerState = 0;
@ -98,89 +97,112 @@ void ccGLUseProgram( GLuint program )
#endif // CC_ENABLE_GL_STATE_CACHE #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) void ccGLBlendFunc(GLenum sfactor, GLenum dfactor)
{ {
#if CC_ENABLE_GL_STATE_CACHE #if CC_ENABLE_GL_STATE_CACHE
if( sfactor != s_eBlendingSource || dfactor != s_eBlendingDest ) { if (sfactor != s_eBlendingSource || dfactor != s_eBlendingDest)
{
s_eBlendingSource = sfactor; s_eBlendingSource = sfactor;
s_eBlendingDest = dfactor; s_eBlendingDest = dfactor;
glBlendFunc( sfactor, dfactor ); SetBlending(sfactor, dfactor);
} }
#else #else
glBlendFunc( sfactor, dfactor ); SetBlending( sfactor, dfactor );
#endif // CC_ENABLE_GL_STATE_CACHE #endif // CC_ENABLE_GL_STATE_CACHE
} }
GLenum ccGLGetActiveTexture( void ) void ccGLBlendResetToCache(void)
{ {
glBlendEquation(GL_FUNC_ADD);
#if CC_ENABLE_GL_STATE_CACHE #if CC_ENABLE_GL_STATE_CACHE
return s_eCurrentActiveTexture + GL_TEXTURE0; SetBlending(s_eBlendingSource, s_eBlendingDest);
#else #else
GLenum activeTexture; SetBlending(CC_BLEND_SRC, CC_BLEND_DST);
glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&activeTexture); #endif // CC_ENABLE_GL_STATE_CACHE
return activeTexture;
#endif
} }
void ccGLActiveTexture( GLenum textureEnum ) void ccGLBindTexture2DN(GLuint textureUnit, GLuint textureId)
{ {
#if CC_ENABLE_GL_STATE_CACHE #if CC_ENABLE_GL_STATE_CACHE
CCAssert( (textureEnum - GL_TEXTURE0) < kCCMaxActiveTexture, "cocos2d ERROR: Increase kCCMaxActiveTexture to kCCMaxActiveTexture!"); CCAssert(textureUnit < kCCMaxActiveTexture, "textureUnit is too big");
if( (textureEnum - GL_TEXTURE0) != s_eCurrentActiveTexture ) { if( s_uCurrentBoundTexture[textureUnit] != textureId )
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 )
{ {
s_uCurrentBoundTexture[ s_eCurrentActiveTexture ] = textureId; s_uCurrentBoundTexture[textureUnit] = textureId;
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureId ); glBindTexture(GL_TEXTURE_2D, textureId );
} }
#else #else
glActiveTexture(GL_TEXTURE0 + textureUnit);
glBindTexture(GL_TEXTURE_2D, textureId ); glBindTexture(GL_TEXTURE_2D, textureId );
#endif #endif
} }
void ccGLDeleteTexture( GLuint textureId ) void ccGLDeleteTexture( GLuint textureId )
{
ccGLDeleteTextureN(0, textureId);
}
void ccGLDeleteTextureN(GLuint textureUnit, GLuint textureId)
{ {
#if CC_ENABLE_GL_STATE_CACHE #if CC_ENABLE_GL_STATE_CACHE
if( textureId == s_uCurrentBoundTexture[ s_eCurrentActiveTexture ] ) if (s_uCurrentBoundTexture[textureUnit] == textureId)
s_uCurrentBoundTexture[ s_eCurrentActiveTexture ] = -1; {
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 #endif
glDeleteTextures(1, &textureId );
} }
void ccGLEnable( ccGLServerState flags ) void ccGLEnable( ccGLServerState flags )
{ {
#if CC_ENABLE_GL_STATE_CACHE #if CC_ENABLE_GL_STATE_CACHE
int enabled = 0; // int enabled = 0;
//
/* GL_BLEND */ // /* GL_BLEND */
if( (enabled = (flags & CC_GL_BLEND)) != (s_eGLServerState & CC_GL_BLEND) ) { // if( (enabled = (flags & CC_GL_BLEND)) != (s_eGLServerState & CC_GL_BLEND) ) {
if( enabled ) { // if( enabled ) {
glEnable( GL_BLEND ); // glEnable( GL_BLEND );
s_eGLServerState |= CC_GL_BLEND; // s_eGLServerState |= CC_GL_BLEND;
} else { // } else {
glDisable( GL_BLEND ); // glDisable( GL_BLEND );
s_eGLServerState &= ~CC_GL_BLEND; // s_eGLServerState &= ~CC_GL_BLEND;
} // }
} // }
#else #else
if( flags & CC_GL_BLEND ) // if( flags & CC_GL_BLEND )
glEnable( GL_BLEND ); // glEnable( GL_BLEND );
else // else
glDisable( GL_BLEND ); // glDisable( GL_BLEND );
#endif #endif
} }
@ -188,6 +210,8 @@ void ccGLEnable( ccGLServerState flags )
void ccGLEnableVertexAttribs( unsigned int flags ) void ccGLEnableVertexAttribs( unsigned int flags )
{ {
ccGLBindVAO(0);
/* Position */ /* Position */
bool enablePosition = flags & kCCVertexAttribFlag_Position; bool enablePosition = flags & kCCVertexAttribFlag_Position;

View File

@ -55,11 +55,12 @@ typedef enum {
// CC_GL_SCISSOR_TEST = 1 << 0, // CC_GL_SCISSOR_TEST = 1 << 0,
// CC_GL_STENCIL_TEST = 1 << 1, // CC_GL_STENCIL_TEST = 1 << 1,
// CC_GL_DEPTH_TEST = 1 << 2, // CC_GL_DEPTH_TEST = 1 << 2,
CC_GL_BLEND = 1 << 3, // CC_GL_BLEND = 1 << 3,
// CC_GL_DITHER = 1 << 4, // 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_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; } ccGLServerState;
@ -70,19 +71,19 @@ typedef enum {
If CC_ENABLE_GL_STATE_CACHE it will reset the GL state cache. If CC_ENABLE_GL_STATE_CACHE it will reset the GL state cache.
@since v2.0.0 @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. /** 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. If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glUseProgram() directly.
@since v2.0.0 @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. /** 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. If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glDeleteProgram() directly.
@since v2.0.0 @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. /** Uses a blending function in case it not already used.
If CC_ENABLE_GL_STATE_CACHE is disabled, it will the glBlendFunc() directly. 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); 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 /** sets the projection matrix as dirty
@since v2.0.0 @since v2.0.0
*/ */
void CC_DLL ccSetProjectionMatrixDirty( void ); void CC_DLL ccSetProjectionMatrixDirty(void);
/** Will enable the vertex attribs that are passed as flags. /** Will enable the vertex attribs that are passed as flags.
Possible flags: Possible flags:
@ -106,26 +113,20 @@ void CC_DLL ccSetProjectionMatrixDirty( void );
@since v2.0.0 @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 the texture is not already bound to texture unit 0, it binds it.
If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glActiveTexture() directly. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly.
@since v2.0.0 @since v2.1.0
*/ */
void CC_DLL ccGLActiveTexture(GLenum textureEnum ); void ccGLBindTexture2D(GLuint textureId);
/** 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 );
/** 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. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glBindTexture() directly.
@since v2.0.0 @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. /** 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. 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); 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. /** It will enable / disable the server side GL states.
If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glEnable() directly. If CC_ENABLE_GL_STATE_CACHE is disabled, it will call glEnable() directly.
@since v2.0.0 @since v2.0.0

View File

@ -480,7 +480,7 @@ void CCTexture2D::drawAtPoint(const CCPoint& point)
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
m_pShaderProgram->use(); m_pShaderProgram->use();
m_pShaderProgram->setUniformForModelViewProjectionMatrix(); m_pShaderProgram->setUniformsForBuiltins();
ccGLBindTexture2D( m_uName ); ccGLBindTexture2D( m_uName );
@ -506,7 +506,7 @@ void CCTexture2D::drawInRect(const CCRect& rect)
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords ); ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position | kCCVertexAttribFlag_TexCoords );
m_pShaderProgram->use(); m_pShaderProgram->use();
m_pShaderProgram->setUniformForModelViewProjectionMatrix(); m_pShaderProgram->setUniformsForBuiltins();
ccGLBindTexture2D( m_uName ); ccGLBindTexture2D( m_uName );