1、头文件
//LightTest.h class LightTest : public Layer { public: CREATE_FUNC(LightTest); LightTest(); virtual ~LightTest(); virtual void update(float delta); void SwitchLight(Ref* sender,LightType lightType);//转换光源 private: void addSprite();//添加精灵 void addLights();//添加光源 private: AmbientLight *_ambientLight; //环境光,想四周发射光线,模拟一个屋子的环境,光线来源方向不定。 DirectionLight *_directionalLight; //方向光,表示一个非常远的光源,投射光线是平行的,用来模拟太阳光 PointLight *_pointLight; //点光,从空间某点向四周均匀发射有限长的光线,用来模拟向四周发射状的光 SpotLight *_spotLight; //聚光,从某点发射一个圆锥形状,用来模拟台灯 Label *_ambientLightLabel; Label *_directionalLightLabel; Label *_pointLightLabel; Label *_spotLightLabel; };
2、Cpp文件
#include "LightTest.h" //构造函数,初始化除环境光AmbientLight之外的三种光为nullptr LightTest::LightTest() : _directionalLight(nullptr),_pointLight(nullptr),_spotLight(nullptr) { addSprite();//添加精灵 addLights();//添加光源 scheduleUpdate();//帧更新 //设置摄像机位置 auto s = Director::getInstance()->getWinSize(); //参数1:透视相机的视野,通常在40-60度范围 //参数2:相机的长宽比,通常视窗的宽度除以视窗的高度 //参数3:近点平面距离 //参数4:原点平面距离 auto camera = Camera::createPerspective(60,(GLfloat)s.width/s.height,1.0f,1000.0f); camera->setCameraFlag(CameraFlag::USER1);//设置相机Flag camera->setPosition3D(Vec3(0.0,100,100));//设置相机3D坐标 //参数1:目标的中心位置,参数2:向上的向量 camera->lookAt(Vec3(0.0,0.0,0.0),Vec3(0.0,1.0,0.0)); addChild(camera); //添加相机转换的开光,Label控件 TTFConfig ttfConfig("fonts/arial.ttf",30); _ambientLightLabel = Label::createWithTTF(ttfConfig,"Ambient Light ON"); _ambientLightLabel->retain(); auto menuItem0 = MenuItemLabel::create(_ambientLightLabel,CC_CALLBACK_1(LightTest::SwitchLight,this,LightType::AMBIENT)); _directionalLightLabel = Label::createWithTTF(ttfConfig,"Directional Light OFF"); _directionalLightLabel->retain(); auto menuItem1 = MenuItemLabel::create(_directionalLightLabel,LightType::DIRECTIONAL)); _pointLightLabel = Label::createWithTTF(ttfConfig,"Point Light OFF"); _pointLightLabel->retain(); auto menuItem2 = MenuItemLabel::create(_pointLightLabel,LightType::POINT)); _spotLightLabel = Label::createWithTTF(ttfConfig,"Spot Light OFF"); _spotLightLabel->retain(); auto menuItem3 = MenuItemLabel::create(_spotLightLabel,LightType::SPOT)); auto menu = Menu::create(menuItem0,menuItem1,menuItem2,menuItem3,nullptr); menu->setPosition(Vec2::ZERO); menuItem0->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT); menuItem0->setPosition( Vec2(VisibleRect::left().x,VisibleRect::top().y-50) ); menuItem1->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT); menuItem1->setPosition( Vec2(VisibleRect::left().x,VisibleRect::top().y-100) ); menuItem2->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT); menuItem2->setPosition( Vec2(VisibleRect::left().x,VisibleRect::top().y -150)); menuItem3->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT); menuItem3->setPosition( Vec2(VisibleRect::left().x,VisibleRect::top().y -200)); addChild(menu); } //析构资源 LightTest::~LightTest() { if (_spotLightLabel) _spotLightLabel->release(); if (_pointLightLabel) _pointLightLabel->release(); if (_directionalLightLabel) _directionalLightLabel->release(); if (_spotLight) _spotLight->release(); if (_pointLight) _pointLight->release(); if (_directionalLight) _directionalLight->release(); if (_ambientLight) _ambientLight->release(); } //添加精灵 void LightTest::addSprite() { auto s = Director::getInstance()->getWinSize(); { //创建3D对象,c3b是二进制文件,通过FBX模型文件进行二次转换得到。 //obj:FBX是一种通用导出格式,可通过maya和max导出,maya和max默认导出obj格式文件。 //c3t:通过FBX模型文件转换后生成的Json文件,体积大载入慢,不提倡使用 //c3b:二进制文件,数据内容与c3t一样,体积小,速度快,提倡使用 //注意:.c3b文件的使用需和它对应的贴图拷贝到Resource目录下,否则,运行时找不到资源。 std::string fileName = "orc.c3b"; //创建3D精灵对象 auto sprite = Sprite3D::create(fileName); sprite->setRotation3D(Vec3(0.0,180.0,0.0)); sprite->setPosition(Vec2(0.0,0.0)); sprite->setScale(2.0); //创建3D精灵对象 auto sp = Sprite3D::create("axe.c3b"); //通过骨骼名称获得连接点 sprite->getAttachNode("Bip001 R Hand")->addChild(sp); //创建3D动画 auto animation = Animation3D::create(fileName); if (animation) { auto animate = Animate3D::create(animation); sprite->runAction(RepeatForever::create(animate));//3D精灵执行3D动画 } addChild(sprite); //设置精灵的Mask,该值与相机的flag进行&运算为真,则对相机可见 sprite->setCameraMask(2); } { //同上 std::string fileName = "sphere.c3b"; auto sprite = Sprite3D::create(fileName); sprite->setPosition(Vec2(30.0,0.0)); addChild(sprite); sprite->setCameraMask(2); } { //同上 std::string fileName = "sphere.c3b"; auto sprite = Sprite3D::create(fileName); sprite->setScale(0.5f); sprite->setPosition(Vec2(-50.0,0.0)); addChild(sprite); sprite->setCameraMask(2); } { //同上 std::string fileName = "sphere.c3b"; auto sprite = Sprite3D::create(fileName); sprite->setScale(0.5f); sprite->setPosition(Vec2(-30.0,10.0)); addChild(sprite); sprite->setCameraMask(2); } } //添加光源 void LightTest::addLights() { auto s = Director::getInstance()->getWinSize(); //环境光 _ambientLight = AmbientLight::create(Color3B(200,200,200)); _ambientLight->retain(); _ambientLight->setEnabled(true);//开启光源 addChild(_ambientLight); _ambientLight->setCameraMask(2);//确保相机可见 //方向光,参数1:光源方向.参数2:光源颜色 _directionalLight = DirectionLight::create(Vec3(-1.0f,-1.0f,0.0f),Color3B(200,200)); _directionalLight->retain(); _directionalLight->setEnabled(false);//光源关闭 addChild(_directionalLight); _directionalLight->setCameraMask(2);//确保相机可见 //点光,参数1:光源的位置,参数2:光源的颜色。参数3:光源范围 _pointLight = PointLight::create(Vec3(0.0f,0.0f,200),10000.0f); _pointLight->retain(); _pointLight->setEnabled(false);//光源关闭 addChild(_pointLight); _pointLight->setCameraMask(2);//确保相机可见 //聚光,参数1:方向。参数2:位置。参数3:颜色,参数4:内圆弧度。参数5:外圆弧度。参数6:光源范围 _spotLight = SpotLight::create(Vec3(-1.0f,Vec3(0.0f,0.5,10000.0f); _spotLight->retain(); _spotLight->setEnabled(false);//光源关闭 addChild(_spotLight); _spotLight->setCameraMask(2);//确保相机可见 { auto tintto1 = TintTo::create(4,255); auto tintto2 = TintTo::create(4,255,0); auto tintto3 = TintTo::create(4,0); auto tintto4 = TintTo::create(4,255); auto seq = Sequence::create(tintto1,tintto2,tintto3,tintto4,nullptr); _ambientLight->runAction(RepeatForever::create(seq));//光源执行渐隐动作 } { auto tintto1 = TintTo::create(4,0); auto tintto2 = TintTo::create(4,255); auto tintto4 = TintTo::create(4,nullptr); _directionalLight->runAction(RepeatForever::create(seq));//光源执行渐隐动作 } { auto tintto1 = TintTo::create(4,255); auto seq = Sequence::create(tintto2,tintto1,nullptr); _pointLight->runAction(RepeatForever::create(seq));//光源执行渐隐动作 } { auto tintto1 = TintTo::create(4,255); auto seq = Sequence::create(tintto3,nullptr); _spotLight->runAction(RepeatForever::create(seq));//光源执行渐隐动作 } } //帧更新 void LightTest::update( float delta ) { static float angleDelta = 0.0; if (_directionalLight) { _directionalLight->setRotation3D(Vec3(-45.0,-CC_RADIANS_TO_DEGREES(angleDelta),0.0f));//设置旋转角度,宏是弧度转化为角度 } //cosf与sinf:float版的cos和sin if (_pointLight) { _pointLight->setPositionX(100.0f * cosf(angleDelta + 2.0 * delta)); _pointLight->setPositionY(100.0f); _pointLight->setPositionZ(100.0f * sinf(angleDelta + 2.0 * delta)); } if (_spotLight) { _spotLight->setPositionX(100.0f * cosf(angleDelta + 4.0 * delta)); _spotLight->setPositionY(100.0f); _spotLight->setPositionZ(100.0f * sinf(angleDelta + 4.0 * delta)); _spotLight->setDirection(-Vec3(cosf(angleDelta + 4.0 * delta),sinf(angleDelta + 4.0 * delta))); } angleDelta += delta; // update(delta); } //光源开关 void LightTest::SwitchLight( Ref* sender,LightType lightType ) { switch (lightType) { case LightType::AMBIENT: { char str[32]; bool isON = !_ambientLight->isEnabled(); sprintf(str,"Ambient Light %s",isON == true? "ON":"OFF"); _ambientLight->setEnabled(isON); _ambientLightLabel->setString(str); } break; case LightType::DIRECTIONAL: { char str[32]; bool isON = !_directionalLight->isEnabled(); sprintf(str,"Directional Light %s",isON == true? "ON":"OFF"); _directionalLight->setEnabled(isON); _directionalLightLabel->setString(str); } break; case LightType::POINT: { char str[32]; bool isON = !_pointLight->isEnabled(); sprintf(str,"Point Light %s",isON == true? "ON":"OFF"); _pointLight->setEnabled(isON); _pointLightLabel->setString(str); } break; case LightType::SPOT: { char str[32]; bool isON = !_spotLight->isEnabled(); sprintf(str,"Spot Light %s",isON == true? "ON":"OFF"); _spotLight->setEnabled(isON); _spotLightLabel->setString(str); } break; default: break; } }
3、使用
在HelloWorldScene.cpp中的
createScene()中,创建LightTest的对象,加入Scene