.h文件的内容如下:
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" class HelloWorld : public cocos2d::Layer { public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // implement the "static create()" method manually void cylinderUpdate(float dt); float _cylinder_texture_offset; float _shining_duraion; cocos2d::GLProgramState * _state; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) cocos2d::EventListenerCustom* _backToForegroundListener; #endif CREATE_FUNC(HelloWorld); }; #endif // __HELLOWORLD_SCENE_H__
.cpp的文件内容如下:
#include "HelloWorldScene.h" #include "cocostudio/CocoStudio.h" #include "ui/CocosGUI.h" //#include "2d/CCCameraBackgroundBrush.h" #include "extensions/Particle3D/PU/CCPUParticleSystem3D.h" #include <algorithm> USING_NS_CC; using namespace cocostudio::timeline; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if (!Layer::init()) { return false; } _cylinder_texture_offset = 0; _shining_duraion = 0; Size visibleSize = Director::getInstance()->getVisibleSize(); //use custom camera auto camera = Camera::createPerspective(60, visibleSize.width / visibleSize.height, 0.1f, 200); camera->setCameraFlag(CameraFlag::USER1); //create cylinder auto cylinder = Sprite3D::create("Sprite3DTest/cylinder.c3b"); //create and set our custom shader auto shader = GLProgram::createWithFilenames("Sprite3DTest/cylinder.vert", "Sprite3DTest/cylinder.frag"); _state = GLProgramState::create(shader); cylinder->setGLProgramState(_state); _state->setUniformFloat("offset", _cylinder_texture_offset); _state->setUniformFloat("duration", _shining_duraion); //pass mesh's attribute to shader long offset = 0; auto attributeCount = cylinder->getMesh()->getMeshVertexAttribCount(); for (auto i = 0; i < attributeCount; i++) { auto meshattribute = cylinder->getMesh()->getMeshVertexAttribute(i); _state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], meshattribute.size, meshattribute.type, GL_FALSE, cylinder->getMesh()->getVertexSizeInBytes(), (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } //create the second texture for cylinder auto shining_texture = Director::getInstance()->getTextureCache()->addImage("Sprite3DTest/caustics.png"); Texture2D::TexParams tRepeatParams;//set texture parameters tRepeatParams.magFilter = GL_NEAREST; tRepeatParams.minFilter = GL_NEAREST; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; shining_texture->setTexParameters(tRepeatParams); //pass the texture sampler to our custom shader _state->setUniformTexture("caustics", shining_texture); this->addChild(cylinder); this->setCameraMask(2); this->addChild(camera); //adjust cylinder's position & rotation cylinder->setPosition3D(Vec3(0, -15, -50)); cylinder->setRotation3D(Vec3(-90, 0, 0)); //the callback function update cylinder's texcoord schedule(schedule_selector(HelloWorld::cylinderUpdate)); } void HelloWorld::cylinderUpdate(float dt) { //callback function to update cylinder's texcoord static bool fade_in = true; _cylinder_texture_offset += 0.3*dt; _cylinder_texture_offset = (_cylinder_texture_offset >1) ? 0 : _cylinder_texture_offset; if (fade_in) { _shining_duraion += 0.5*dt; if (_shining_duraion>1) fade_in = false; } else { _shining_duraion -= 0.5*dt; if (_shining_duraion<0) fade_in = true; } //pass the result to shader _state->setUniformFloat("offset", _cylinder_texture_offset); _state->setUniformFloat("duration", _shining_duraion); }
运行效果: