Water *Water::create(const std::string& fileName, const std::string& waveFileOne, const std::string& waveFileTwo, const cocos2d::Size& size, float hSpeed, float vSpeed, float saturation) { Water *water = new (std::nothrow) Water(); if (water && water->initWithFile(fileName, cocos2d::Rect(0, 0, size.width, size.height))) { water->autorelease(); auto TexCache = cocos2d::Director::getInstance()->getTextureCache(); auto wave2 = TexCache->addImage(waveFileOne); auto wave1 = TexCache->addImage(waveFileTwo); cocos2d::Texture2D::TexParams wave1TexParams = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT }; cocos2d::Texture2D::TexParams wave2TexParams = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT }; wave1->setTexParameters(wave1TexParams); wave2->setTexParameters(wave2TexParams); auto glprogram = cocos2d::GLProgram::createWithFilenames("shader3D/water.vsh", "shader3D/water.fsh"); auto glprogramstate = cocos2d::GLProgramState::getOrCreateWithGLProgram(glprogram); water->setGLProgramState(glprogramstate); glprogramstate->setUniformTexture("u_wave1", wave1); glprogramstate->setUniformTexture("u_wave2", wave2); glprogramstate->setUniformFloat("saturateValue", saturation); glprogramstate->setUniformFloat("verticalSpeed", vSpeed); glprogramstate->setUniformFloat("horizontalSpeed", hSpeed); return water; } CC_SAFE_DELETE(water); return nullptr; }
Sprite3DUVAnimationTest::Sprite3DUVAnimationTest() { //the offset use to translating texture _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.1,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(Sprite3DUVAnimationTest::cylinderUpdate)); }
// on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } //the offset use to translating texture this->cylinder_texture_offset = 0; this->shining_duraion = 0; Size visibleSize = Director::getInstance()->getVisibleSize(); //use custom camera auto camera = Camera::createPerspective(60,visibleSize.width/visibleSize.height,0.1,200); camera->setCameraFlag(CameraFlag::USER1); auto cylinder = Sprite3D::create("cylinder.c3b"); auto shader =GLProgram::createWithFilenames("cylinder.vert","cylinder.frag"); state = GLProgramState::create(shader); cylinder->setGLProgramState(state); //set attrib to shader long offset = 0; auto attributeCount = cylinder->getMesh()->getMeshVertexAttribCount(); for (auto k = 0; k < attributeCount; k++) { auto meshattribute = cylinder->getMesh()->getMeshVertexAttribute(k); state->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], meshattribute.size, meshattribute.type, GL_FALSE, cylinder->getMesh()->getVertexSizeInBytes(), (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } auto shining_texture = Director::getInstance()->getTextureCache()->addImage("caustics.png"); Texture2D::TexParams tRepeatParams; tRepeatParams.magFilter = GL_LINEAR_MIPMAP_LINEAR; tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; shining_texture->setTexParameters(tRepeatParams); state->setUniformTexture("caustics",shining_texture); cylinder->setPosition3D(Vec3(0,-15,-50)); cylinder->setRotation3D(Vec3(-90,0,0)); this->addChild(cylinder); this->setCameraMask(2); this->addChild(camera); schedule(schedule_selector(HelloWorld::cylinderUpdate)); return true; }
Sprite3D* Sprite3D::createSprite3DNode(NodeData* nodedata,ModelData* modeldata,const MaterialDatas& materialdatas) { auto sprite = new (std::nothrow) Sprite3D(); if (sprite) { sprite->setName(nodedata->id); auto mesh = Mesh::create(nodedata->id, getMeshIndexData(modeldata->subMeshId)); if (modeldata->matrialId == "" && materialdatas.materials.size()) { const NTextureData* textureData = materialdatas.materials[0].getTextureData(NTextureData::Usage::Diffuse); if (!textureData->filename.empty()) mesh->setTexture(textureData->filename); } else { const NMaterialData* materialData=materialdatas.getMaterialData(modeldata->matrialId); if(materialData) { const NTextureData* textureData = materialData->getTextureData(NTextureData::Usage::Diffuse); if(textureData && !textureData->filename.empty()) { auto tex = Director::getInstance()->getTextureCache()->addImage(textureData->filename); if(tex) { Texture2D::TexParams texParams; texParams.minFilter = GL_LINEAR; texParams.magFilter = GL_LINEAR; texParams.wrapS = textureData->wrapS; texParams.wrapT = textureData->wrapT; tex->setTexParameters(texParams); mesh->setTexture(tex); mesh->_isTransparent = (materialData->getTextureData(NTextureData::Usage::Transparency) != nullptr); } } } } // set locale transform Vec3 pos; Quaternion qua; Vec3 scale; nodedata->transform.decompose(&scale, &qua, &pos); sprite->setPosition3D(pos); sprite->setRotationQuat(qua); sprite->setScaleX(scale.x); sprite->setScaleY(scale.y); sprite->setScaleZ(scale.z); sprite->addMesh(mesh); sprite->autorelease(); sprite->genGLProgramState(); } return sprite; }
//波光效果动画 void Tortoise::initUVAnimation() { // 将vsh与fsh装配成一个完整的Shader文件。 auto glprogram = GLProgram::createWithFilenames("3D/UVAnimation.vsh", "3D/UVAnimation.fsh"); // 由Shader文件创建这个Shader auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram); // 给精灵设置所用的Shader _sprite->setGLProgramState(glprogramstate); //创建海龟所用的贴图。 auto textrue1 = Director::getInstance()->getTextureCache()->addImage("3D/tortoise.png"); //将贴图设置给Shader中的变量值u_texture1 glprogramstate->setUniformTexture("u_texture1", textrue1); //创建波光贴图。 auto textrue2 = Director::getInstance()->getTextureCache()->addImage("3D/caustics.png"); //将贴图设置给Shader中的变量值u_lightTexture glprogramstate->setUniformTexture("u_lightTexture", textrue2); //注意,对于波光贴图,我们希望它在进行UV动画时能产生四方连续效果,必须设置它的纹理UV寻址方式为GL_REPEAT。 Texture2D::TexParams tRepeatParams; tRepeatParams.magFilter = GL_LINEAR_MIPMAP_LINEAR; tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; textrue2->setTexParameters(tRepeatParams); //在这里,我们设置一个波光的颜色,这里设置为白色。 Vec4 tLightColor(1.0,1.0,1.0,1.0); glprogramstate->setUniformVec4("v_LightColor",tLightColor); //下面这一段,是为了将我们自定义的Shader与我们的模型顶点组织方式进行匹配。模型的顶点数据一般包括位置,法线,色彩,纹理,以及骨骼绑定信息。而Shader需要将内部相应的顶点属性通道与模型相应的顶点属性数据进行绑定才能正确显示出顶点。 long offset = 0; auto attributeCount = _sprite->getMesh()->getMeshVertexAttribCount(); for (auto k = 0; k < attributeCount; k++) { auto meshattribute = _sprite->getMesh()->getMeshVertexAttribute(k); glprogramstate->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], meshattribute.size, meshattribute.type, GL_FALSE, _sprite->getMesh()->getVertexSizeInBytes(), (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } //uv滚动初始值设为0 _lightAni.x = _lightAni.y = 0; }//end initUVAnimation
void RepeatableSprite::initTextureRectAndPosition() { setAnchorPoint({0, 0}); setPosition({0, 0}); auto size = cocos2d::EGLView::getInstance()->getDesignResolutionSize(); setTextureRect({0, 0, size.width, size.height}); auto tex = getTexture(); if (tex) { if (tex->getPixelsWide() != cocos2d::ccNextPOT(tex->getPixelsWide()) || tex->getPixelsHigh() != cocos2d::ccNextPOT(tex->getPixelsHigh())) { throw std::invalid_argument("RepeatableSprite Texture has to be a power of two!"); } tex->setTexParameters({ GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT }); } }
Sprite3D* Sprite3D::createSprite3DNode(NodeData* nodedata,ModelData* modeldata,const MaterialDatas& matrialdatas) { auto sprite = new (std::nothrow) Sprite3D(); if (sprite) { sprite->setName(nodedata->id); auto mesh = Mesh::create(nodedata->id, getMeshIndexData(modeldata->subMeshId)); if (modeldata->matrialId == "" && matrialdatas.materials.size()) { const NTextureData* textureData = matrialdatas.materials[0].getTextureData(NTextureData::Usage::Diffuse); if (!textureData->filename.empty()) mesh->setTexture(textureData->filename); } else { const NMaterialData* materialData=matrialdatas.getMaterialData(modeldata->matrialId); if(materialData) { const NTextureData* textureData = materialData->getTextureData(NTextureData::Usage::Diffuse); if(textureData && !textureData->filename.empty()) { auto tex = Director::getInstance()->getTextureCache()->addImage(textureData->filename); if(tex) { Texture2D::TexParams texParams; texParams.minFilter = GL_LINEAR; texParams.magFilter = GL_LINEAR; texParams.wrapS = textureData->wrapS; texParams.wrapT = textureData->wrapT; tex->setTexParameters(texParams); mesh->setTexture(tex); mesh->_isTransparent = (materialData->getTextureData(NTextureData::Usage::Transparency) != nullptr); } } } } sprite->setAdditionalTransform(&nodedata->transform); sprite->addMesh(mesh); sprite->autorelease(); sprite->genGLProgramState(); } return sprite; }
void UVEffectSprite::InitShader() { auto p = new GLProgram(); p->initWithFilenames("Shaders/uv.vsh", "Shaders/uv.fsh"); p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_POSITION, GLProgram::VERTEX_ATTRIB_POSITION); p->bindAttribLocation(GLProgram::ATTRIBUTE_NAME_TEX_COORD, GLProgram::VERTEX_ATTRIB_TEX_COORDS); p->link(); p->updateUniforms(); this->setGLProgram(p); auto textrue = Director::getInstance()->getTextureCache()->addImage("soroll_uv3.png"); Texture2D::TexParams tRepeatParams;//设置纹理渲染方式 tRepeatParams.magFilter = GL_LINEAR_MIPMAP_LINEAR; tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; textrue->setTexParameters(tRepeatParams);//将贴图设置给Shader中的变量值u_texture1 _lightani.x = _lightani.y = 0.0f; getGLProgramState()->setUniformTexture("u_lightTexture", textrue); getGLProgramState()->setUniformVec2("v_animLight", _lightani); }
CameraBackgroundSkyBoxBrush* CameraBackgroundSkyBoxBrush::create(const std::string& positive_x, const std::string& negative_x, const std::string& positive_y, const std::string& negative_y, const std::string& positive_z, const std::string& negative_z) { auto texture = TextureCube::create(positive_x, negative_x, positive_y, negative_y, positive_z, negative_z); if (texture == nullptr) return nullptr; Texture2D::TexParams tRepeatParams; tRepeatParams.magFilter = GL_LINEAR; tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_CLAMP_TO_EDGE; tRepeatParams.wrapT = GL_CLAMP_TO_EDGE; texture->setTexParameters(tRepeatParams); auto ret = new(std::nothrow)CameraBackgroundSkyBoxBrush(); ret->init(); ret->setTexture(texture); ret->autorelease(); return ret; }
void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& matrialdatas, bool singleSprite) { Node* node=nullptr; for(const auto& it : nodedata->modelNodeDatas) { if(it) { if(it->bones.size() > 0 || singleSprite) { auto mesh = Mesh::create(nodedata->id, getMeshIndexData(it->subMeshId)); if(mesh) { _meshes.pushBack(mesh); if (_skeleton && it->bones.size()) { auto skin = MeshSkin::create(_skeleton, it->bones, it->invBindPose); mesh->setSkin(skin); } mesh->_visibleChanged = std::bind(&Sprite3D::onAABBDirty, this); if (it->matrialId == "" && matrialdatas.materials.size()) { const NTextureData* textureData = matrialdatas.materials[0].getTextureData(NTextureData::Usage::Diffuse); mesh->setTexture(textureData->filename); } else { const NMaterialData* materialData=matrialdatas.getMaterialData(it->matrialId); if(materialData) { const NTextureData* textureData = materialData->getTextureData(NTextureData::Usage::Diffuse); if(textureData && !textureData->filename.empty()) { auto tex = Director::getInstance()->getTextureCache()->addImage(textureData->filename); if(tex) { Texture2D::TexParams texParams; texParams.minFilter = GL_LINEAR; texParams.magFilter = GL_LINEAR; texParams.wrapS = textureData->wrapS; texParams.wrapT = textureData->wrapT; tex->setTexParameters(texParams); mesh->setTexture(tex); mesh->_isTransparent = (materialData->getTextureData(NTextureData::Usage::Transparency) != nullptr); } } } } } } else { auto sprite = createSprite3DNode(nodedata,it,matrialdatas); if (sprite) { if(root) { root->addChild(sprite); } } node=sprite; } } } if(nodedata->modelNodeDatas.size() ==0 ) { node= Node::create(); if(node) { node->setName(nodedata->id); Vec3 pos, scale; Quaternion quat; nodedata->transform.decompose(&scale, &quat, &pos); node->setPosition3D(pos); node->setRotationQuat(quat); node->setScaleX(scale.x); node->setScaleY(scale.y); node->setScaleZ(scale.z); if(root) { root->addChild(node); } } } for(const auto& it : nodedata->children) { createNode(it,node, matrialdatas, singleSprite); } }
// cocos2d-x doesn't support Samplers yet. But will be added soon bool Material::parseSampler(GLProgramState* glProgramState, Properties* samplerProperties) { CCASSERT(samplerProperties->getId(), "Sampler must have an id. The id is the uniform name"); // required auto filename = samplerProperties->getString("path"); auto texture = Director::getInstance()->getTextureCache()->addImage(filename); if (!texture) { CCLOG("Invalid filepath"); return false; } // optionals { Texture2D::TexParams texParams; // mipmap bool usemipmap = false; const char* mipmap = getOptionalString(samplerProperties, "mipmap", "false"); if (mipmap && strcasecmp(mipmap, "true")==0) { texture->generateMipmap(); usemipmap = true; } // valid options: REPEAT, CLAMP const char* wrapS = getOptionalString(samplerProperties, "wrapS", "CLAMP_TO_EDGE"); if (strcasecmp(wrapS, "REPEAT")==0) texParams.wrapS = GL_REPEAT; else if(strcasecmp(wrapS, "CLAMP_TO_EDGE")==0) texParams.wrapS = GL_CLAMP_TO_EDGE; else CCLOG("Invalid wrapS: %s", wrapS); // valid options: REPEAT, CLAMP const char* wrapT = getOptionalString(samplerProperties, "wrapT", "CLAMP_TO_EDGE"); if (strcasecmp(wrapT, "REPEAT")==0) texParams.wrapT = GL_REPEAT; else if(strcasecmp(wrapT, "CLAMP_TO_EDGE")==0) texParams.wrapT = GL_CLAMP_TO_EDGE; else CCLOG("Invalid wrapT: %s", wrapT); // valid options: NEAREST, LINEAR, NEAREST_MIPMAP_NEAREST, LINEAR_MIPMAP_NEAREST, NEAREST_MIPMAP_LINEAR, LINEAR_MIPMAP_LINEAR const char* minFilter = getOptionalString(samplerProperties, "minFilter", usemipmap ? "LINEAR_MIPMAP_NEAREST" : "LINEAR"); if (strcasecmp(minFilter, "NEAREST")==0) texParams.minFilter = GL_NEAREST; else if(strcasecmp(minFilter, "LINEAR")==0) texParams.minFilter = GL_LINEAR; else if(strcasecmp(minFilter, "NEAREST_MIPMAP_NEAREST")==0) texParams.minFilter = GL_NEAREST_MIPMAP_NEAREST; else if(strcasecmp(minFilter, "LINEAR_MIPMAP_NEAREST")==0) texParams.minFilter = GL_LINEAR_MIPMAP_NEAREST; else if(strcasecmp(minFilter, "NEAREST_MIPMAP_LINEAR")==0) texParams.minFilter = GL_NEAREST_MIPMAP_LINEAR; else if(strcasecmp(minFilter, "LINEAR_MIPMAP_LINEAR")==0) texParams.minFilter = GL_LINEAR_MIPMAP_LINEAR; else CCLOG("Invalid minFilter: %s", minFilter); // valid options: NEAREST, LINEAR const char* magFilter = getOptionalString(samplerProperties, "magFilter", "LINEAR"); if (strcasecmp(magFilter, "NEAREST")==0) texParams.magFilter = GL_NEAREST; else if(strcasecmp(magFilter, "LINEAR")==0) texParams.magFilter = GL_LINEAR; else CCLOG("Invalid magFilter: %s", magFilter); texture->setTexParameters(texParams); } glProgramState->setUniformTexture(samplerProperties->getId(), texture); return true; }
bool FishLayer::init() { //加载模型文件 std::string fileName = "tortoise.c3b"; m_Sprite = Sprite3D::create(fileName); m_Sprite->setScale(0.1f); auto s = Director::getInstance()->getWinSize(); m_Sprite->setPosition(Vec2(s.width / 2.f, s.height / 2.f)); addChild(m_Sprite); //获取骨骼动画信息 m_Animation3D = Animation3D::create(fileName); if (m_Animation3D) { //从起始到1.933秒截取为游泳动作 m_Swim = Animate3D::create(m_Animation3D, 0.f, 1.933f); m_Swim->retain(); //让精灵循环播放游泳和的受伤动作 Sequence* pSequence = Sequence::create(m_Swim,NULL); m_Sprite->runAction(RepeatForever::create(pSequence)); } // 将vsh与fsh装配成一个完整的Shader文件。 auto glprogram = GLProgram::createWithFilenames("UVAnimation.vsh", "UVAnimation.fsh"); // 由Shader文件创建这个Shader auto glprogramstate = GLProgramState::getOrCreateWithGLProgram(glprogram); // 给精灵设置所用的Shader m_Sprite->setGLProgramState(glprogramstate); //创建海龟所用的贴图。 auto textrue1 = Director::getInstance()->getTextureCache()->addImage("tortoise.png"); //将贴图设置给Shader中的变量值u_texture1 glprogramstate->setUniformTexture("u_texture1", textrue1); //创建波光贴图。 auto textrue2 = Director::getInstance()->getTextureCache()->addImage("caustics.png"); //将贴图设置给Shader中的变量值u_lightTexture glprogramstate->setUniformTexture("u_lightTexture", textrue2); //注意,对于波光贴图,我们希望它在进行UV动画时能产生四方连续效果,必须设置它的纹理UV寻址方式为GL_REPEAT。 Texture2D::TexParams tRepeatParams; tRepeatParams.magFilter = GL_LINEAR_MIPMAP_LINEAR; tRepeatParams.minFilter = GL_LINEAR; tRepeatParams.wrapS = GL_REPEAT; tRepeatParams.wrapT = GL_REPEAT; textrue2->setTexParameters(tRepeatParams); //在这里,我们设置一个波光的颜色,这里设置为白色。 Vec4 tLightColor(1.0,1.0,1.0,1.0); glprogramstate->setUniformVec4("v_LightColor",tLightColor); //下面这一段,是为了将我们自定义的Shader与我们的模型顶点组织方式进行匹配。模型的顶点数据一般包括位置,法线,色彩,纹理,以及骨骼绑定信息。而Shader需要将内部相应的顶点属性通道与模型相应的顶点属性数据进行绑定才能正确显示出顶点。 long offset = 0; auto attributeCount = m_Sprite->getMesh()->getMeshVertexAttribCount(); for (auto k = 0; k < attributeCount; k++) { auto meshattribute = m_Sprite->getMesh()->getMeshVertexAttribute(k); glprogramstate->setVertexAttribPointer(s_attributeNames[meshattribute.vertexAttrib], meshattribute.size, meshattribute.type, GL_FALSE, m_Sprite->getMesh()->getVertexSizeInBytes(), (GLvoid*)offset); offset += meshattribute.attribSizeBytes; } //uv滚动初始值设为0 m_LightAni.x = m_LightAni.y = 0; return true; }