#include "ShaderTest2.h" #include "ShaderTest.h" #include "../testResource.h" #include "cocos2d.h" #include "renderer/CCRenderCommand.h" #include "renderer/CCCustomCommand.h" namespace ShaderTest2 { static std::function createFunctions[] = { CL(NormalSpriteTest), CL(GreyScaleSpriteTest), CL(BlurSpriteTest), CL(NoiseSpriteTest), CL(EdgeDetectionSpriteTest), CL(BloomSpriteTest), CL(CelShadingSpriteTest), CL(LensFlareSpriteTest), CL(OutlineShadingSpriteTest) }; static unsigned int TEST_CASE_COUNT = sizeof(ShaderTest2::createFunctions) / sizeof(ShaderTest2::createFunctions[0]); static int sceneIdx=-1; Layer* createTest(int index) { auto layer = (createFunctions[index])();; return layer; } Layer* nextAction(); Layer* backAction(); Layer* restartAction(); Layer* nextAction() { sceneIdx++; sceneIdx = sceneIdx % TEST_CASE_COUNT; return createTest(sceneIdx); } Layer* backAction() { sceneIdx--; if( sceneIdx < 0 ) sceneIdx = TEST_CASE_COUNT -1; return createTest(sceneIdx); } Layer* restartAction() { return createTest(sceneIdx); } } ShaderTestDemo2::ShaderTestDemo2() { } void ShaderTestDemo2::backCallback(Ref* sender) { auto s = ShaderTestScene2::create(); s->addChild( ShaderTest2::backAction() ); Director::getInstance()->replaceScene(s); } void ShaderTestDemo2::nextCallback(Ref* sender) { auto s = ShaderTestScene2::create(); s->addChild( ShaderTest2::nextAction() ); Director::getInstance()->replaceScene(s); } void ShaderTestDemo2::restartCallback(Ref* sender) { auto s = ShaderTestScene2::create(); s->addChild(ShaderTest2::restartAction()); Director::getInstance()->replaceScene(s); } void ShaderTestScene2::runThisTest() { auto layer = ShaderTest2::nextAction(); addChild(layer); Director::getInstance()->replaceScene(this); } template class ShaderSpriteCreator { public: static spriteType* createSprite(const std::string& filename) { spriteType* ret = spriteType::create(); ret->setTexture(filename); ret->initShader(); ret->setBackgroundNotification(); return ret; } }; class ShaderSprite : public Sprite { public: ShaderSprite(); ~ShaderSprite(); virtual void initShader(); void setBackgroundNotification(); virtual void draw(Renderer *renderer, const Matrix &transform, bool transformUpdated) override; void listenBackToForeground(Ref *obj); protected: virtual void buildCustomUniforms() = 0; virtual void setCustomUniforms() = 0; protected: std::string _fragSourceFile; std::string _vertSourceFile; protected: CustomCommand _renderCommand; void onDraw(const Matrix &transform, bool transformUpdated); }; ShaderSprite::ShaderSprite() :_vertSourceFile("") { } ShaderSprite::~ShaderSprite() { } void ShaderSprite::setBackgroundNotification() { #if CC_ENABLE_CACHE_TEXTURE_DATA auto listener = EventListenerCustom::create(EVENT_COME_TO_FOREGROUND, [this](EventCustom* event){ this->setShaderProgram(nullptr); this->initShader(); }); _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); #endif } void ShaderSprite::initShader() { auto fileUtiles = FileUtils::getInstance(); auto fragmentFilePath = fileUtiles->fullPathForFilename(_fragSourceFile); auto fragSource = fileUtiles->getStringFromFile(fragmentFilePath); std::string vertSource; if (_vertSourceFile.empty()) { vertSource = ccPositionTextureColor_vert; }else{ std::string vertexFilePath = fileUtiles->fullPathForFilename(_vertSourceFile); vertSource = fileUtiles->getStringFromFile(vertexFilePath); } auto program = new GLProgram(); program->initWithByteArrays(vertSource.c_str(), fragSource.c_str()); setShaderProgram(program); program->release(); CHECK_GL_ERROR_DEBUG(); program->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION); program->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_COLOR, GLProgram::VERTEX_ATTRIB_COLOR); program->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS); CHECK_GL_ERROR_DEBUG(); program->link(); CHECK_GL_ERROR_DEBUG(); program->updateUniforms(); CHECK_GL_ERROR_DEBUG(); buildCustomUniforms(); CHECK_GL_ERROR_DEBUG(); } void ShaderSprite::draw(Renderer *renderer, const Matrix &transform, bool transformUpdated) { _renderCommand.init(_globalZOrder); _renderCommand.func = CC_CALLBACK_0(ShaderSprite::onDraw, this, transform, transformUpdated); renderer->addCommand(&_renderCommand); } void ShaderSprite::onDraw(const Matrix &transform, bool transformUpdated) { auto shader = getShaderProgram(); shader->use(); shader->setUniformsForBuiltins(transform); setCustomUniforms(); GL::enableVertexAttribs(cocos2d::GL::VERTEX_ATTRIB_FLAG_POS_COLOR_TEX ); GL::blendFunc(_blendFunc.src, _blendFunc.dst); GL::bindTexture2D( getTexture()->getName()); // // Attributes // #define kQuadSize sizeof(_quad.bl) size_t offset = (size_t)&_quad; // vertex int diff = offsetof( V3F_C4B_T2F, vertices); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff)); // texCoods diff = offsetof( V3F_C4B_T2F, texCoords); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_TEX_COORDS, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff)); // color diff = offsetof( V3F_C4B_T2F, colors); glVertexAttribPointer(GLProgram::VERTEX_ATTRIB_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff)); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); CC_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, 4); } class NormalSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(NormalSprite); NormalSprite(); protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; NormalSprite::NormalSprite() { _fragSourceFile = "Shaders/example_normal.fsh"; } void NormalSprite::buildCustomUniforms() { } void NormalSprite::setCustomUniforms() { } class GreyScaleSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(GreyScaleSprite); GreyScaleSprite(); protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; GreyScaleSprite::GreyScaleSprite() { _fragSourceFile = "Shaders/example_greyScale.fsh"; } void GreyScaleSprite::buildCustomUniforms() { } void GreyScaleSprite::setCustomUniforms() { } class BlurSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(BlurSprite); BlurSprite(); void setBlurSize(float f); protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); protected: int _blurRadius; Vector2 _pixelSize; int _samplingRadius; float _scale; float _cons; float _weightSum; GLuint pixelSizeLocation; GLuint coefficientLocation; }; BlurSprite::BlurSprite() { _fragSourceFile = "Shaders/example_Blur.fsh"; } void BlurSprite::buildCustomUniforms() { auto s = getTexture()->getContentSizeInPixels(); _blurRadius = 0; _pixelSize = Vector2(1/s.width, 1/s.height); _samplingRadius = 0; setBlurSize(3.0f); auto program = getShaderProgram(); pixelSizeLocation = program->getUniformLocation("onePixelSize"); coefficientLocation = program->getUniformLocation("gaussianCoefficient"); } void BlurSprite::setCustomUniforms() { auto program = getShaderProgram(); program->setUniformLocationWith2f(pixelSizeLocation, _pixelSize.x, _pixelSize.y); program->setUniformLocationWith4f(coefficientLocation, _samplingRadius, _scale,_cons,_weightSum); } void BlurSprite::setBlurSize(float f) { if(_blurRadius == (int)f) return; _blurRadius = (int)f; _samplingRadius = _blurRadius; if (_samplingRadius > 10) { _samplingRadius = 10; } if (_blurRadius > 0) { float sigma = _blurRadius / 2.0f; _scale = -0.5f / (sigma * sigma); _cons = -1.0f * _scale / 3.141592f; _weightSum = -_cons; float weight; int squareX; for(int dx = 0; dx <= _samplingRadius; ++dx) { squareX = dx * dx; weight = _cons * exp(squareX * _scale); _weightSum += 2.0 * weight; for (int dy = 1; dy <= _samplingRadius; ++dy) { weight = _cons * exp((squareX + dy * dy) * _scale); _weightSum += 4.0 * weight; } } } log("_blurRadius:%d",_blurRadius); } class NoiseSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(NoiseSprite); NoiseSprite(); private: GLfloat _resolution[2]; GLuint _resolutionLoc; protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; NoiseSprite::NoiseSprite() { _fragSourceFile = "Shaders/example_Noisy.fsh"; } void NoiseSprite::buildCustomUniforms() { auto program = getShaderProgram(); _resolutionLoc = program->getUniformLocation("resolution"); } void NoiseSprite::setCustomUniforms() { _resolution[0] = getTexture()->getContentSizeInPixels().width; _resolution[1] = getTexture()->getContentSizeInPixels().height; getShaderProgram()->setUniformLocationWith2fv(_resolutionLoc, _resolution, 1); } class EdgeDetectionSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(EdgeDetectionSprite); EdgeDetectionSprite(); private: GLfloat _resolution[2]; GLuint _resolutionLoc; protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; EdgeDetectionSprite::EdgeDetectionSprite() { _fragSourceFile = "Shaders/example_edgeDetection.fsh"; } void EdgeDetectionSprite::buildCustomUniforms() { auto program = getShaderProgram(); _resolutionLoc = program->getUniformLocation("resolution"); } void EdgeDetectionSprite::setCustomUniforms() { _resolution[0] = getTexture()->getContentSizeInPixels().width; _resolution[1] = getTexture()->getContentSizeInPixels().height; getShaderProgram()->setUniformLocationWith2fv(_resolutionLoc, _resolution, 1); } class BloomSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(BloomSprite); BloomSprite(); private: GLfloat _resolution[2]; GLuint _resolutionLoc; protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; BloomSprite::BloomSprite() { _fragSourceFile = "Shaders/example_bloom.fsh"; } void BloomSprite::buildCustomUniforms() { auto program = getShaderProgram(); _resolutionLoc = program->getUniformLocation("resolution"); } void BloomSprite::setCustomUniforms() { _resolution[0] = getTexture()->getContentSizeInPixels().width; _resolution[1] = getTexture()->getContentSizeInPixels().height; getShaderProgram()->setUniformLocationWith2fv(_resolutionLoc, _resolution, 1); } class CelShadingSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(CelShadingSprite); CelShadingSprite(); private: GLfloat _resolution[2]; GLuint _resolutionLoc; protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; CelShadingSprite::CelShadingSprite() { _fragSourceFile = "Shaders/example_celShading.fsh"; } void CelShadingSprite::buildCustomUniforms() { auto program = getShaderProgram(); _resolutionLoc = program->getUniformLocation("resolution"); } void CelShadingSprite::setCustomUniforms() { _resolution[0] = getTexture()->getContentSizeInPixels().width; _resolution[1] = getTexture()->getContentSizeInPixels().height; getShaderProgram()->setUniformLocationWith2fv(_resolutionLoc, _resolution, 1); } class LensFlareSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(LensFlareSprite); LensFlareSprite(); private: GLfloat _resolution[2]; GLfloat _textureResolution[2]; GLuint _resolutionLoc; GLuint _textureResolutionLoc; protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; LensFlareSprite::LensFlareSprite() { _fragSourceFile = "Shaders/example_lensFlare.fsh"; } void LensFlareSprite::buildCustomUniforms() { auto program = getShaderProgram(); _resolutionLoc = program->getUniformLocation("resolution"); _textureResolutionLoc = program->getUniformLocation("textureResolution"); } void LensFlareSprite::setCustomUniforms() { _textureResolution[0] = getTexture()->getContentSizeInPixels().width; _textureResolution[1] = getTexture()->getContentSizeInPixels().height; _resolution[0] = getContentSize().width; _resolution[1] = getContentSize().height; getShaderProgram()->setUniformLocationWith2fv(_resolutionLoc, _resolution, 1); getShaderProgram()->setUniformLocationWith2fv(_textureResolutionLoc, _textureResolution, 1); } NormalSpriteTest::NormalSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); NormalSprite* sprite = NormalSprite::createSprite("Images/powered.png"); sprite->setPosition(Vector2(s.width/2, s.height/2)); addChild(sprite); } } GreyScaleSpriteTest::GreyScaleSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); GreyScaleSprite* sprite = GreyScaleSprite::createSprite("Images/powered.png"); sprite->setPosition(Vector2(s.width * 0.75, s.height/2)); auto sprite2 = Sprite::create("Images/powered.png"); sprite2->setPosition(Vector2(s.width * 0.25, s.height/2)); addChild(sprite); addChild(sprite2); } } BlurSpriteTest::BlurSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); BlurSprite* sprite = BlurSprite::createSprite("Images/powered.png"); sprite->setPosition(Vector2(s.width * 0.75, s.height/2)); auto sprite2 = Sprite::create("Images/powered.png"); sprite2->setPosition(Vector2(s.width * 0.25, s.height/2)); addChild(sprite); addChild(sprite2); } } NoiseSpriteTest::NoiseSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); NoiseSprite* sprite = NoiseSprite::createSprite("Images/powered.png"); sprite->setPosition(Vector2(s.width * 0.75, s.height/2)); auto sprite2 = Sprite::create("Images/powered.png"); sprite2->setPosition(Vector2(s.width * 0.25, s.height/2)); addChild(sprite); addChild(sprite2); } } EdgeDetectionSpriteTest::EdgeDetectionSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); EdgeDetectionSprite* sprite = EdgeDetectionSprite::createSprite("Images/powered.png"); sprite->setPosition(Vector2(s.width * 0.75, s.height/2)); auto sprite2 = Sprite::create("Images/powered.png"); sprite2->setPosition(Vector2(s.width * 0.25, s.height/2)); addChild(sprite); addChild(sprite2); } } BloomSpriteTest::BloomSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); BloomSprite* sprite = BloomSprite::createSprite("Images/stone.png"); sprite->setPosition(Vector2(s.width * 0.75, s.height/2)); auto sprite2 = Sprite::create("Images/stone.png"); sprite2->setPosition(Vector2(s.width * 0.25, s.height/2)); addChild(sprite); addChild(sprite2); } } CelShadingSpriteTest::CelShadingSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); CelShadingSprite* sprite = CelShadingSprite::createSprite("Images/stone.png"); sprite->setPosition(Vector2(s.width * 0.75, s.height/2)); auto sprite2 = Sprite::create("Images/stone.png"); sprite2->setPosition(Vector2(s.width * 0.25, s.height/2)); addChild(sprite); addChild(sprite2); } } LensFlareSpriteTest::LensFlareSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); LensFlareSprite* sprite = LensFlareSprite::createSprite("Images/noise.png"); Rect rect = Rect::ZERO; rect.size = Size(480,320); sprite->setPosition(Vector2(s.width * 0.5, s.height/2)); addChild(sprite); } } class OutlineSprite : public ShaderSprite, public ShaderSpriteCreator { public: CREATE_FUNC(OutlineSprite); OutlineSprite(); private: GLuint _outlineColorUniformLocation; GLuint _thresdholdUniformLocation; GLuint _radiusUniformLocation; protected: virtual void buildCustomUniforms(); virtual void setCustomUniforms(); }; OutlineSprite::OutlineSprite() { _fragSourceFile = "Shaders/example_outline.fsh"; _vertSourceFile = "Shaders/example_outline.vsh"; _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; } void OutlineSprite::buildCustomUniforms() { auto program = getShaderProgram(); _outlineColorUniformLocation = program->getUniformLocation("u_outlineColor"); _thresdholdUniformLocation = program->getUniformLocation("u_threshold"); _radiusUniformLocation = program->getUniformLocation("u_radius"); } void OutlineSprite::setCustomUniforms() { GLfloat color[3] = {1.0, 0.2, 0.3}; GLfloat radius = 0.01; GLfloat threshold = 1.75; getShaderProgram()->setUniformLocationWith3fv(_outlineColorUniformLocation, color, 1); getShaderProgram()->setUniformLocationWith1f(_radiusUniformLocation, radius); getShaderProgram()->setUniformLocationWith1f(_thresdholdUniformLocation, threshold); } OutlineShadingSpriteTest::OutlineShadingSpriteTest() { if (ShaderTestDemo2::init()) { auto s = Director::getInstance()->getWinSize(); OutlineSprite* sprite = OutlineSprite::createSprite("Images/grossini_dance_10.png"); sprite->setPosition(Vector2(s.width * 0.75, s.height/2)); auto sprite2 = Sprite::create("Images/grossini_dance_10.png"); sprite2->setPosition(Vector2(s.width * 0.25, s.height/2)); addChild(sprite); addChild(sprite2); } }