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, CC_CALLBACK_1(LightTest::SwitchLight,this,LightType::DIRECTIONAL));
_pointLightLabel = Label::createWithTTF(ttfConfig,"Point Light OFF");
_pointLightLabel->retain();
auto menuItem2 = MenuItemLabel::create(_pointLightLabel, CC_CALLBACK_1(LightTest::SwitchLight,this,LightType::POINT));
_spotLightLabel = Label::createWithTTF(ttfConfig,"Spot Light OFF");
_spotLightLabel->retain();
auto menuItem3 = MenuItemLabel::create(_spotLightLabel, CC_CALLBACK_1(LightTest::SwitchLight,this,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, 200));
_directionalLight->retain();
_directionalLight->setEnabled(false);//光源关闭
addChild(_directionalLight);
_directionalLight->setCameraMask(2);//确保相机可见
//点光,参数1:光源的位置,参数2:光源的颜色。参数3:光源范围
_pointLight = PointLight::create(Vec3(0.0f, 0.0f, 0.0f), Color3B(200, 200, 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, -1.0f, 0.0f), Vec3(0.0f, 0.0f, 0.0f), Color3B(200, 200, 200), 0.0, 0.5, 10000.0f);
_spotLight->retain();
_spotLight->setEnabled(false);//光源关闭
addChild(_spotLight);
_spotLight->setCameraMask(2);//确保相机可见
{
auto tintto1 = TintTo::create(4, 0, 0, 255);
auto tintto2 = TintTo::create(4, 0, 255, 0);
auto tintto3 = TintTo::create(4, 255, 0, 0);
auto tintto4 = TintTo::create(4, 255, 255, 255);
auto seq = Sequence::create(tintto1,tintto2, tintto3, tintto4, nullptr);
_ambientLight->runAction(RepeatForever::create(seq));//光源执行渐隐动作
}
{
auto tintto1 = TintTo::create(4, 255, 0, 0);
auto tintto2 = TintTo::create(4, 0, 255, 0);
auto tintto3 = TintTo::create(4, 0, 0, 255);
auto tintto4 = TintTo::create(4, 255, 255, 255);
auto seq = Sequence::create(tintto1,tintto2, tintto3, tintto4, nullptr);
_directionalLight->runAction(RepeatForever::create(seq));//光源执行渐隐动作
}
{
auto tintto1 = TintTo::create(4, 255, 0, 0);
auto tintto2 = TintTo::create(4, 0, 255, 0);
auto tintto3 = TintTo::create(4, 0, 0, 255);
auto tintto4 = TintTo::create(4, 255, 255, 255);
auto seq = Sequence::create(tintto2, tintto1, tintto3, tintto4, nullptr);
_pointLight->runAction(RepeatForever::create(seq));//光源执行渐隐动作
}
{
auto tintto1 = TintTo::create(4, 255, 0, 0);
auto tintto2 = TintTo::create(4, 0, 255, 0);
auto tintto3 = TintTo::create(4, 0, 0, 255);
auto tintto4 = TintTo::create(4, 255, 255, 255);
auto seq = Sequence::create(tintto3, tintto2, tintto1, tintto4, 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), 1.0, 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