From 10afb9b9afbd9c29c93563da99a7b8e418e9737b Mon Sep 17 00:00:00 2001 From: songchengjiang Date: Mon, 18 Aug 2014 17:10:07 +0800 Subject: [PATCH] Finished Point Light Finished Directional Light Finished Spot Light --- cocos/3d/CCLight.cpp | 18 +- cocos/3d/CCLight.h | 11 - cocos/renderer/CCGLProgram.cpp | 66 +++-- cocos/renderer/CCGLProgram.h | 6 +- cocos/renderer/ccShader_3D_Color.frag | 52 +++- cocos/renderer/ccShader_3D_ColorTex.frag | 57 +++- cocos/renderer/ccShader_3D_PositionTex.vert | 69 +---- .../Classes/LightTest/LightTestDemo.cpp | 267 +++++++++++++----- .../Classes/LightTest/LightTestDemo.h | 81 +++++- .../Resources/Sprite3DTest/sphere.c3b | Bin 0 -> 23890 bytes .../Resources/Sprite3DTest/spheretex.png | Bin 0 -> 1720 bytes 11 files changed, 429 insertions(+), 198 deletions(-) create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/sphere.c3b create mode 100644 tests/cpp-tests/Resources/Sprite3DTest/spheretex.png diff --git a/cocos/3d/CCLight.cpp b/cocos/3d/CCLight.cpp index cff1812fae..d407c39a9c 100644 --- a/cocos/3d/CCLight.cpp +++ b/cocos/3d/CCLight.cpp @@ -4,8 +4,7 @@ NS_CC_BEGIN Light3D::Light3D() -: _isEnabled(false) -, _range(0.0f) +: _range(0.0f) , _innerAngle(0.0f) , _outerAngle(0.0f) { @@ -35,17 +34,6 @@ Light3D::LightType Light3D::getLightType() return _lightType; } -void Light3D::setEnabled( bool isEnabled ) -{ - _isEnabled = isEnabled; -} - -bool Light3D::getEnabled() -{ - return _isEnabled; -} - - void Light3D::setRange( float range ) { _range = range; @@ -91,7 +79,7 @@ void Light3D::onEnter() auto scene = getScene(); if (scene) { - auto lights = scene->_lights; + auto &lights = scene->_lights; auto iter = std::find(lights.begin(), lights.end(), this); if (iter == lights.end()) lights.push_back(this); @@ -103,7 +91,7 @@ void Light3D::onExit() auto scene = getScene(); if (scene) { - auto lights = scene->_lights; + auto &lights = scene->_lights; auto iter = std::find(lights.begin(), lights.end(), this); if (iter != lights.end()) lights.erase(iter); diff --git a/cocos/3d/CCLight.h b/cocos/3d/CCLight.h index 266304b486..a71f5dd570 100644 --- a/cocos/3d/CCLight.h +++ b/cocos/3d/CCLight.h @@ -59,16 +59,6 @@ public: */ LightType getLightType(); - /** - * Sets light enabled. - */ - void setEnabled(bool isEnabled); - - /** - * Gets light enabled. - */ - bool getEnabled(); - /** * Sets the range of point or spot light. * @@ -133,7 +123,6 @@ CC_CONSTRUCTOR_ACCESS: protected: LightType _lightType; - bool _isEnabled; Vec3 _dir; float _range; float _innerAngle; diff --git a/cocos/renderer/CCGLProgram.cpp b/cocos/renderer/CCGLProgram.cpp index 00322b2d26..edf64b65cc 100644 --- a/cocos/renderer/CCGLProgram.cpp +++ b/cocos/renderer/CCGLProgram.cpp @@ -80,7 +80,8 @@ const char* GLProgram::SHADER_3D_SKINPOSITION_TEXTURE = "Shader3DSkinPositionTex // uniform names -const char* GLProgram::UNIFORM_NAME_LIGHT_SOURCE = "CC_LightSource"; +const char* GLProgram::UNIFORM_NAME_ENABLED_LIGHT_NUM = "CC_EnabledLightNum"; +const char* GLProgram::UNIFORM_NAME_AMBIENT_COLOR = "CC_AmbientColor"; const char* GLProgram::UNIFORM_NAME_P_MATRIX = "CC_PMatrix"; const char* GLProgram::UNIFORM_NAME_MV_MATRIX = "CC_MVMatrix"; const char* GLProgram::UNIFORM_NAME_MVP_MATRIX = "CC_MVPMatrix"; @@ -417,17 +418,18 @@ bool GLProgram::compileShader(GLuint * shader, GLenum type, const GLchar* source "#define CC_MAX_LIGHT 6 \n" "struct LightSource \n" "{ \n" - " vec4 color; \n" - " vec3 position; \n" - " vec3 direction; \n" + " float type; \n" " float range; \n" " float range2; \n" " float innerAngle; \n" " float outerAngle; \n" - " float type; \n" - " float use; \n" + " vec4 color; \n" + " vec3 position; \n" + " vec3 direction; \n" "}; \n" "uniform LightSource CC_LightSource[CC_MAX_LIGHT];\n" + "uniform int CC_EnabledLightNum; \n" + "uniform vec4 CC_AmbientColor; \n" }; const GLchar *sources[] = { @@ -498,7 +500,8 @@ void GLProgram::bindAttribLocation(const std::string &attributeName, GLuint inde void GLProgram::updateUniforms() { - _builtInUniforms[UNIFORM_LIGHT_SOURCE] = glGetUniformLocation(_program, UNIFORM_NAME_LIGHT_SOURCE); + _builtInUniforms[UNIFORM_ENABLED_LIGHT_NUM] = glGetUniformLocation(_program, UNIFORM_NAME_ENABLED_LIGHT_NUM); + _builtInUniforms[UNIFORM_AMBIENT_COLOR] = glGetUniformLocation(_program, UNIFORM_NAME_AMBIENT_COLOR); _builtInUniforms[UNIFORM_P_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_P_MATRIX); _builtInUniforms[UNIFORM_MV_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MV_MATRIX); _builtInUniforms[UNIFORM_MVP_MATRIX] = glGetUniformLocation(_program, UNIFORM_NAME_MVP_MATRIX); @@ -515,7 +518,7 @@ void GLProgram::updateUniforms() _builtInUniforms[UNIFORM_SAMPLER2] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER2); _builtInUniforms[UNIFORM_SAMPLER3] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER3); - _flags.usesLights = _builtInUniforms[UNIFORM_LIGHT_SOURCE] != -1; + _flags.usesLights = _builtInUniforms[UNIFORM_ENABLED_LIGHT_NUM] != -1; _flags.usesP = _builtInUniforms[UNIFORM_P_MATRIX] != -1; _flags.usesMV = _builtInUniforms[UNIFORM_MV_MATRIX] != -1; _flags.usesMVP = _builtInUniforms[UNIFORM_MVP_MATRIX] != -1; @@ -931,31 +934,38 @@ void GLProgram::setUniformsForBuiltins(const Mat4 &matrixMV) auto scene = director->getRunningScene(); if (scene) { - auto lights = scene->getLights(); + auto &lights = scene->getLights(); CCASSERT(lights.size() < CC_MAX_LIGHT_NUM, ""); - - GLfloat lightSources[16 * CC_MAX_LIGHT_NUM]; - unsigned int sz = sizeof(lightSources); - memset(lightSources, 0, sizeof(lightSources)); unsigned int idx = 0; - for (auto iter : lights) + char str[32]; + for (unsigned int i = 0; i < lights.size(); ++i) { - const Color3B &col = iter->getColor(); - const Vec3 &pos = iter->getPosition3D(); - const Vec3 &dir = iter->getDirection(); - lightSources[0 + idx] = col.r / 255.0f;lightSources[1 + idx] = col.g / 255.0f;lightSources[2 + idx] = col.b / 255.0f;lightSources[3 + idx] = 1.0f; - lightSources[4 + idx] = pos.x;lightSources[5 + idx] = pos.y;lightSources[6 + idx] = pos.z; - lightSources[7 + idx] = dir.x;lightSources[8 + idx] = dir.y;lightSources[9 + idx] = dir.z; - lightSources[10 + idx] = iter->getRange(); - lightSources[11 + idx] = iter->getRange() * iter->getRange(); - lightSources[12 + idx] = iter->getInnerAngle(); - lightSources[13 + idx] = iter->getOuterAngle(); - lightSources[14 + idx] = static_cast(iter->getLightType()); - lightSources[15 + idx] = static_cast(iter->getEnabled()); - idx += 16; + Light3D *light = lights[i]; + const Color3B &col = light->getColor(); + const Vec3 &pos = light->getPosition3D(); + const Vec3 &dir = light->getDirection(); + + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "type"); + setUniformLocationWith1f(glGetUniformLocation(_program, str), static_cast(light->getLightType())); + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "range"); + setUniformLocationWith1f(glGetUniformLocation(_program, str), light->getRange()); + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "range2"); + setUniformLocationWith1f(glGetUniformLocation(_program, str), light->getRange() * light->getRange()); + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "innerAngle"); + setUniformLocationWith1f(glGetUniformLocation(_program, str), light->getInnerAngle()); + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "outerAngle"); + setUniformLocationWith1f(glGetUniformLocation(_program, str), light->getOuterAngle()); + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "color"); + setUniformLocationWith4f(glGetUniformLocation(_program, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f, 1.0f); + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "position"); + setUniformLocationWith3f(glGetUniformLocation(_program, str), pos.x, pos.y, pos.z); + sprintf_s(str, 32, "CC_LightSource[%d].%s", i, "direction"); + setUniformLocationWith3f(glGetUniformLocation(_program, str), dir.x, dir.y, dir.z); + idx += 8; } - setUniformLocationWith1fv(_builtInUniforms[GLProgram::UNIFORM_LIGHT_SOURCE], lightSources, 16 * CC_MAX_LIGHT_NUM); + setUniformLocationWith1i(_builtInUniforms[GLProgram::UNIFORM_ENABLED_LIGHT_NUM], (GLint)lights.size()); + setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_AMBIENT_COLOR], scene->getAmbientColor().r, scene->getAmbientColor().g, scene->getAmbientColor().b, scene->getAmbientColor().a); } } } diff --git a/cocos/renderer/CCGLProgram.h b/cocos/renderer/CCGLProgram.h index e326d699b6..abf752d707 100644 --- a/cocos/renderer/CCGLProgram.h +++ b/cocos/renderer/CCGLProgram.h @@ -96,7 +96,8 @@ public: enum { - UNIFORM_LIGHT_SOURCE, + UNIFORM_ENABLED_LIGHT_NUM, + UNIFORM_AMBIENT_COLOR, UNIFORM_P_MATRIX, UNIFORM_MV_MATRIX, UNIFORM_MVP_MATRIX, @@ -137,7 +138,8 @@ public: static const char* SHADER_3D_SKINPOSITION_TEXTURE; // uniform names - static const char* UNIFORM_NAME_LIGHT_SOURCE; + static const char* UNIFORM_NAME_ENABLED_LIGHT_NUM; + static const char* UNIFORM_NAME_AMBIENT_COLOR; static const char* UNIFORM_NAME_P_MATRIX; static const char* UNIFORM_NAME_MV_MATRIX; static const char* UNIFORM_NAME_MVP_MATRIX; diff --git a/cocos/renderer/ccShader_3D_Color.frag b/cocos/renderer/ccShader_3D_Color.frag index f286667fdd..fea1b318d8 100644 --- a/cocos/renderer/ccShader_3D_Color.frag +++ b/cocos/renderer/ccShader_3D_Color.frag @@ -7,9 +7,59 @@ varying lowp vec4 DestinationColor; varying vec4 DestinationColor; \n#endif\n uniform vec4 u_color; +varying vec4 ePosition; +varying vec3 eNormal; + +void PointLight(int n, vec4 ePosition, vec3 eNormal, out vec4 intensity) +{ + if (distance(CC_LightSource[n].position, ePosition.xyz) < CC_LightSource[n].range) + { + vec4 p = vec4(CC_LightSource[n].position, 1.0); + p -= ePosition; + intensity.xyz += CC_LightSource[n].color * max(0.0, dot(normalize(p.xyz), eNormal)); + } + intensity.w = 1.0; +} + +void DirectionalLight(int n, vec3 eNormal, out vec4 intensity) +{ + intensity.xyz += CC_LightSource[n].color * max(0.0, dot(normalize(-CC_LightSource[n].direction), eNormal)); + intensity.w = 1.0; +} + +void SpotLight(int n, vec4 ePosition, vec3 eNormal, out vec4 intensity) +{ + if (distance(CC_LightSource[n].position, ePosition.xyz) < CC_LightSource[n].range) + { + vec3 lightDir = CC_LightSource[n].position - ePosition.xyz; + lightDir = normalize(lightDir); + float spotDot = dot(lightDir, normalize(-CC_LightSource[n].direction)); + float innerCos = cos(CC_LightSource[n].innerAngle); + float outerCos = cos(CC_LightSource[n].outerAngle); + float factor = smoothstep(outerCos, innerCos, spotDot); + intensity.xyz += CC_LightSource[n].color * max(0.0, dot(lightDir, eNormal)) * factor; + } + intensity.w = 1.0; +} void main(void) { - gl_FragColor = u_color; + vec3 normal = normalize(eNormal); + vec4 intensity = vec4(0.0); + for (int i = 0; i < CC_EnabledLightNum; ++i) + { + if (CC_LightSource[i].type == 0.0f) + DirectionalLight(i, normal, intensity); + else + if (CC_LightSource[i].type == 1.0f) + PointLight(i, ePosition, normal, intensity); + else + SpotLight(i, ePosition, normal, intensity); + } + + if (intensity.w == 0.0) + gl_FragColor = u_color; + else + gl_FragColor = u_color * (CC_AmbientColor + intensity); } ); diff --git a/cocos/renderer/ccShader_3D_ColorTex.frag b/cocos/renderer/ccShader_3D_ColorTex.frag index 1819bea738..71788ce1d1 100644 --- a/cocos/renderer/ccShader_3D_ColorTex.frag +++ b/cocos/renderer/ccShader_3D_ColorTex.frag @@ -3,18 +3,63 @@ const char* cc3D_ColorTex_frag = STRINGIFY( \n#ifdef GL_ES\n varying mediump vec2 TextureCoordOut; -varying mediump vec4 LightIntensityOut; \n#else\n varying vec2 TextureCoordOut; -varying vec4 LightIntensityOut; \n#endif\n uniform vec4 u_color; +varying vec4 ePosition; +varying vec3 eNormal; + +void PointLight(int n, vec4 ePosition, vec3 eNormal, out vec4 intensity) +{ + if (distance(CC_LightSource[n].position, ePosition.xyz) < CC_LightSource[n].range) + { + vec4 p = vec4(CC_LightSource[n].position, 1.0); + p -= ePosition; + intensity.xyz += CC_LightSource[n].color * max(0.0, dot(normalize(p.xyz), eNormal)); + } + intensity.w = 1.0; +} + +void DirectionalLight(int n, vec3 eNormal, out vec4 intensity) +{ + intensity.xyz += CC_LightSource[n].color * max(0.0, dot(normalize(-CC_LightSource[n].direction), eNormal)); + intensity.w = 1.0; +} + +void SpotLight(int n, vec4 ePosition, vec3 eNormal, out vec4 intensity) +{ + if (distance(CC_LightSource[n].position, ePosition.xyz) < CC_LightSource[n].range) + { + vec3 lightDir = CC_LightSource[n].position - ePosition.xyz; + lightDir = normalize(lightDir); + float spotDot = dot(lightDir, normalize(-CC_LightSource[n].direction)); + float innerCos = cos(CC_LightSource[n].innerAngle); + float outerCos = cos(CC_LightSource[n].outerAngle); + float factor = smoothstep(outerCos, innerCos, spotDot); + intensity.xyz += CC_LightSource[n].color * max(0.0, dot(lightDir, eNormal)) * factor; + } + intensity.w = 1.0; +} void main(void) { - if (LightIntensityOut.w == 0.0) - gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color; - else - gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color * LightIntensityOut; + vec3 normal = normalize(eNormal); + vec4 intensity = vec4(0.0); + for (int i = 0; i < CC_EnabledLightNum; ++i) + { + if (CC_LightSource[i].type == 0.0f) + DirectionalLight(i, normal, intensity); + else + if (CC_LightSource[i].type == 1.0f) + PointLight(i, ePosition, normal, intensity); + else + SpotLight(i, ePosition, normal, intensity); + } + + if (intensity.w == 0.0) + gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color; + else + gl_FragColor = texture2D(CC_Texture0, TextureCoordOut) * u_color * (CC_AmbientColor + intensity); } ); diff --git a/cocos/renderer/ccShader_3D_PositionTex.vert b/cocos/renderer/ccShader_3D_PositionTex.vert index 536541f53e..c76714bfca 100644 --- a/cocos/renderer/ccShader_3D_PositionTex.vert +++ b/cocos/renderer/ccShader_3D_PositionTex.vert @@ -5,37 +5,16 @@ attribute vec4 a_position; attribute vec2 a_texCoord; attribute vec3 a_normal; varying vec2 TextureCoordOut; -varying vec4 LightIntensityOut; - -vec4 PointLight(int n, vec4 ePosition, vec3 eNormal) -{ - vec4 intensity = vec4(0.0); - if (0.0 < CC_LightSource[n].use) - { - vec4 p = vec4(CC_LightSource[n].position, 1.0) * CC_MVMatrix; - p -= ePosition; - intensity.xyz = CC_LightSource[n].color * max(0.0, dot(normalize(p.xyz), eNormal)); - intensity.w = 1.0; - } - - return intensity; -} +varying vec4 ePosition; +varying vec3 eNormal; void main(void) { - vec4 ePosition = CC_MVMatrix * a_position; - vec3 eNormal = CC_NormalMatrix * a_normal; - - vec4 intensity = vec4(0.0); - for (int i = 0; i < CC_MAX_LIGHT; ++i) - { - intensity += PointLight(i, ePosition, eNormal); - } - LightIntensityOut = intensity; - + ePosition = CC_MVMatrix * a_position; + eNormal = CC_NormalMatrix * a_normal; TextureCoordOut = a_texCoord; TextureCoordOut.y = 1.0 - TextureCoordOut.y; - gl_Position = CC_PMatrix * ePosition; + gl_Position = CC_PMatrix * ePosition; } ); @@ -55,21 +34,8 @@ uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3]; // Varyings varying vec2 TextureCoordOut; -varying vec4 LightIntensityOut; - -vec4 PointLight(int n, vec4 ePosition, vec3 eNormal) -{ - vec4 intensity = vec4(0.0); - if (0.0 < CC_LightSource[n].use) - { - vec4 p = vec4(CC_LightSource[n].position, 1.0) * CC_MVMatrix; - p -= ePosition; - intensity.xyz = CC_LightSource[n].color * max(0.0, dot(normalize(p.xyz), eNormal)); - intensity.w = 1.0; - } - - return intensity; -} +varying vec4 ePosition; +varying vec3 eNormal; void getPositionAndNormal(out vec4 position, out vec3 normal) { @@ -117,8 +83,8 @@ void getPositionAndNormal(out vec4 position, out vec3 normal) position.z = dot(p, matrixPalette3); position.w = p.w; - vec4 n = vec4(a_normal, 0.0); - normal.x = dot(n, matrixPalette1); + vec4 n = vec4(a_normal, 0.0); + normal.x = dot(n, matrixPalette1); normal.y = dot(n, matrixPalette2); normal.z = dot(n, matrixPalette3); } @@ -126,21 +92,14 @@ void getPositionAndNormal(out vec4 position, out vec3 normal) void main() { vec4 position; - vec3 normal; - getPositionAndNormal(position, normal); - - vec4 ePosition = CC_MVMatrix * position; - vec3 eNormal = CC_NormalMatrix * normal; - vec4 intensity = vec4(0.0); - for (int i = 0; i < CC_MAX_LIGHT; ++i) - { - intensity += PointLight(i, ePosition, eNormal); - } - LightIntensityOut = intensity; + vec3 normal; + getPositionAndNormal(position, normal); + ePosition = CC_MVMatrix * position; + eNormal = CC_NormalMatrix * normal; TextureCoordOut = a_texCoord; TextureCoordOut.y = 1.0 - TextureCoordOut.y; - gl_Position = CC_PMatrix * ePosition; + gl_Position = CC_PMatrix * ePosition; } ); \ No newline at end of file diff --git a/tests/cpp-tests/Classes/LightTest/LightTestDemo.cpp b/tests/cpp-tests/Classes/LightTest/LightTestDemo.cpp index 124bce0825..ab9f175aa7 100644 --- a/tests/cpp-tests/Classes/LightTest/LightTestDemo.cpp +++ b/tests/cpp-tests/Classes/LightTest/LightTestDemo.cpp @@ -6,41 +6,41 @@ static int sceneIdx = -1; static std::function createFunctions[] = { - CL(LightTestDemo) + CL(DirectionalLightTestDemo), + CL(PointLightTestDemo), + CL(SpotLightTestDemo) }; #define MAX_LAYER (sizeof(createFunctions) / sizeof(createFunctions[0])) static Layer* nextSpriteTestAction() { - sceneIdx++; - sceneIdx = sceneIdx % MAX_LAYER; + sceneIdx++; + sceneIdx = sceneIdx % MAX_LAYER; - auto layer = (createFunctions[sceneIdx])(); - return layer; + auto layer = (createFunctions[sceneIdx])(); + return layer; } static Layer* backSpriteTestAction() { - sceneIdx--; - int total = MAX_LAYER; - if( sceneIdx < 0 ) - sceneIdx += total; + sceneIdx--; + int total = MAX_LAYER; + if( sceneIdx < 0 ) + sceneIdx += total; - auto layer = (createFunctions[sceneIdx])(); - return layer; + auto layer = (createFunctions[sceneIdx])(); + return layer; } static Layer* restartSpriteTestAction() { - auto layer = (createFunctions[sceneIdx])(); - return layer; + auto layer = (createFunctions[sceneIdx])(); + return layer; } LightTestDemo::LightTestDemo() { - addSprite(); - addLights(); } @@ -50,85 +50,218 @@ LightTestDemo::~LightTestDemo() std::string LightTestDemo::title() const { - return "Point Light"; + return "Point Light"; } std::string LightTestDemo::subtitle() const { - return ""; + return ""; } void LightTestDemo::restartCallback( Ref* sender ) { - auto s = new LightTestScene(); - s->addChild(restartSpriteTestAction()); - Director::getInstance()->replaceScene(s); - s->release(); + auto s = new LightTestScene(); + s->addChild(restartSpriteTestAction()); + Director::getInstance()->replaceScene(s); + s->release(); } void LightTestDemo::nextCallback( Ref* sender ) { - auto s = new LightTestScene(); - s->addChild( nextSpriteTestAction() ); - Director::getInstance()->replaceScene(s); - s->release(); + auto s = new LightTestScene(); + s->addChild( nextSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); } void LightTestDemo::backCallback( Ref* sender ) { - auto s = new LightTestScene(); - s->addChild( backSpriteTestAction() ); - Director::getInstance()->replaceScene(s); - s->release(); -} - -void LightTestDemo::addSprite() -{ - auto s = Director::getInstance()->getWinSize(); - std::string fileName = "Sprite3DTest/orc.c3b"; - auto sprite = Sprite3D::create(fileName); - sprite->setScale(5.0f); - sprite->setRotation3D(Vec3(0,180,0)); - sprite->setPosition(Vec2(s.width/2, s.height/2)); - addChild(sprite); - - auto sp = Sprite3D::create("Sprite3DTest/axe.c3b"); - sprite->getAttachNode("Bip001 R Hand")->addChild(sp); - - auto animation = Animation3D::create(fileName); - if (animation) - { - auto animate = Animate3D::create(animation); - - sprite->runAction(RepeatForever::create(animate)); - } + auto s = new LightTestScene(); + s->addChild( backSpriteTestAction() ); + Director::getInstance()->replaceScene(s); + s->release(); } void LightTestDemo::onEnter() { - BaseTest::onEnter(); + BaseTest::onEnter(); } void LightTestDemo::onExit() { - BaseTest::onExit(); -} - -void LightTestDemo::addLights() -{ - auto s = Director::getInstance()->getWinSize(); - auto light1 = Light3D::Create(Light3D::POINT); - light1->setEnabled(true); - light1->setPosition(Vec2(s.width/2, s.height)); - light1->setColor(Color3B(255, 255, 255)); - - addChild(light1); + BaseTest::onExit(); } void LightTestScene::runThisTest() { - auto layer = nextSpriteTestAction(); - addChild(layer); + auto layer = nextSpriteTestAction(); + addChild(layer); - Director::getInstance()->replaceScene(this); + Director::getInstance()->replaceScene(this); +} + +LightTestScene::LightTestScene() +{ + setAmbientColor(Color4F(0.2f, 0.2f, 0.2f, 1.0f)); +} + +PointLightTestDemo::PointLightTestDemo() + : _pointLight(nullptr) +{ + addSprite(); + addLights(); + scheduleUpdate(); +} + +PointLightTestDemo::~PointLightTestDemo() +{ + if (_pointLight) + _pointLight->release(); +} + +void PointLightTestDemo::addSprite() +{ + auto s = Director::getInstance()->getWinSize(); + std::string fileName = "Sprite3DTest/sphere.c3b"; + auto sprite = Sprite3D::create(fileName); + sprite->setScale(5.0f); + sprite->setPosition(Vec2(s.width/2, s.height/2)); + addChild(sprite); +} + +void PointLightTestDemo::addLights() +{ + auto s = Director::getInstance()->getWinSize(); + _pointLight = Light3D::Create(Light3D::POINT); + _pointLight->setPosition(Vec2(s.width/2, s.height/2)); + _pointLight->setColor(Color3B(128, 128, 128)); + _pointLight->setRange(10000.0f); + _pointLight->retain(); + + addChild(_pointLight); +} + +void PointLightTestDemo::update( float delta ) +{ + auto s = Director::getInstance()->getWinSize(); + static float angleDelta = 0.0; + _pointLight->setPositionX(s.width / 2 + s.width / 4 * cosf(angleDelta)); + _pointLight->setPositionY(s.height / 2); + _pointLight->setPositionZ(s.width / 4 * sinf(angleDelta)); + + angleDelta += delta; + BaseTest::update(delta); +} + +std::string PointLightTestDemo::title() const +{ + return "Point Light"; +} + +DirectionalLightTestDemo::DirectionalLightTestDemo() + : _directionalLight(nullptr) +{ + addSprite(); + addLights(); + scheduleUpdate(); +} + +DirectionalLightTestDemo::~DirectionalLightTestDemo() +{ + if (_directionalLight) + _directionalLight->release(); +} + +std::string DirectionalLightTestDemo::title() const +{ + return "Directional Light"; +} + +void DirectionalLightTestDemo::update( float delta ) +{ + static float angleDelta = 0.0; + _directionalLight->setDirection(-Vec3(cosf(angleDelta), 0.0f, sinf(angleDelta))); + + angleDelta += delta; + BaseTest::update(delta); +} + +void DirectionalLightTestDemo::addSprite() +{ + auto s = Director::getInstance()->getWinSize(); + std::string fileName = "Sprite3DTest/sphere.c3b"; + auto sprite = Sprite3D::create(fileName); + sprite->setScale(5.0f); + sprite->setRotation3D(Vec3(0,180,0)); + sprite->setPosition(Vec2(s.width/2, s.height/2)); + addChild(sprite); +} + +void DirectionalLightTestDemo::addLights() +{ + auto s = Director::getInstance()->getWinSize(); + _directionalLight = Light3D::Create(Light3D::DIRECTIONAL); + _directionalLight->setDirection(Vec3(-1.0f, 0.0f, 0.0f)); + _directionalLight->setColor(Color3B(128, 128, 128)); + _directionalLight->retain(); + + addChild(_directionalLight); +} + +std::string SpotLightTestDemo::title() const +{ + return "Spot Light"; +} + +void SpotLightTestDemo::addSprite() +{ + auto s = Director::getInstance()->getWinSize(); + std::string fileName = "Sprite3DTest/sphere.c3b"; + auto sprite = Sprite3D::create(fileName); + sprite->setScale(5.0f); + sprite->setPosition(Vec2(s.width/2, s.height/2)); + addChild(sprite); +} + +void SpotLightTestDemo::addLights() +{ + auto s = Director::getInstance()->getWinSize(); + _spotLight = Light3D::Create(Light3D::SPOT); + _spotLight->setDirection(Vec3(0.0f, 0.0f, -1.0f)); + _spotLight->setColor(Color3B(128, 128, 128)); + _spotLight->setPosition(Vec2(s.width/2, s.height/2)); + _spotLight->setPositionZ(s.width/2); + _spotLight->setInnerAngle(0.0f); + _spotLight->setOuterAngle(0.4f); + _spotLight->setRange(10000.0f); + _spotLight->retain(); + + addChild(_spotLight); +} + +SpotLightTestDemo::SpotLightTestDemo() + : _spotLight(nullptr) +{ + addSprite(); + addLights(); + scheduleUpdate(); +} + +SpotLightTestDemo::~SpotLightTestDemo() +{ + if (_spotLight) + _spotLight->release(); +} + +void SpotLightTestDemo::update( float delta ) +{ + auto s = Director::getInstance()->getWinSize(); + static float angleDelta = 0.0; + _spotLight->setDirection(-Vec3(cosf(angleDelta), 0.0f, sinf(angleDelta))); + _spotLight->setPositionX(s.width / 2 + s.width / 4 * cosf(angleDelta)); + _spotLight->setPositionY(s.height / 2); + _spotLight->setPositionZ(s.width / 4 * sinf(angleDelta)); + + angleDelta += delta; + BaseTest::update(delta); } diff --git a/tests/cpp-tests/Classes/LightTest/LightTestDemo.h b/tests/cpp-tests/Classes/LightTest/LightTestDemo.h index f98ea4dee4..cb3ed92edb 100644 --- a/tests/cpp-tests/Classes/LightTest/LightTestDemo.h +++ b/tests/cpp-tests/Classes/LightTest/LightTestDemo.h @@ -31,31 +31,86 @@ class LightTestDemo : public BaseTest { public: - CREATE_FUNC(LightTestDemo); - LightTestDemo(); - virtual ~LightTestDemo(); + LightTestDemo(); + virtual ~LightTestDemo(); - virtual std::string title() const; - virtual std::string subtitle() const; + virtual std::string title() const; + virtual std::string subtitle() const; - virtual void restartCallback(Ref* sender); - virtual void nextCallback(Ref* sender); - virtual void backCallback(Ref* sender); + virtual void restartCallback(Ref* sender); + virtual void nextCallback(Ref* sender); + virtual void backCallback(Ref* sender); - virtual void onEnter() override; - virtual void onExit() override; + virtual void onEnter() override; + virtual void onExit() override; +}; + +class PointLightTestDemo : public LightTestDemo +{ +public: + CREATE_FUNC(PointLightTestDemo); + PointLightTestDemo(); + virtual ~PointLightTestDemo(); + + virtual std::string title() const; + + virtual void update(float delta); private: - void addSprite(); - void addLights(); + void addSprite(); + void addLights(); + +private: + Light3D *_pointLight; +}; + +class DirectionalLightTestDemo : public LightTestDemo +{ +public: + CREATE_FUNC(DirectionalLightTestDemo); + DirectionalLightTestDemo(); + virtual ~DirectionalLightTestDemo(); + + virtual std::string title() const; + + virtual void update(float delta); + +private: + + void addSprite(); + void addLights(); + +private: + Light3D *_directionalLight; +}; + +class SpotLightTestDemo : public LightTestDemo +{ +public: + CREATE_FUNC(SpotLightTestDemo); + SpotLightTestDemo(); + virtual ~SpotLightTestDemo(); + + virtual std::string title() const; + + virtual void update(float delta); + +private: + + void addSprite(); + void addLights(); + +private: + Light3D *_spotLight; }; class LightTestScene : public TestScene { public: - virtual void runThisTest(); + LightTestScene(); + virtual void runThisTest(); }; #endif diff --git a/tests/cpp-tests/Resources/Sprite3DTest/sphere.c3b b/tests/cpp-tests/Resources/Sprite3DTest/sphere.c3b new file mode 100644 index 0000000000000000000000000000000000000000..3969dd7da1f09b514e441f42934281e10fc398d1 GIT binary patch literal 23890 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 AApigX literal 0 HcmV?d00001 diff --git a/tests/cpp-tests/Resources/Sprite3DTest/spheretex.png b/tests/cpp-tests/Resources/Sprite3DTest/spheretex.png new file mode 100644 index 0000000000000000000000000000000000000000..94eed4b1dda46c20f8275ffaeb616becfcb4edeb GIT binary patch literal 1720 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G!U;i$lZxy-8q?;Kn_c~qpu?a z!^VE@KZ&eBK4*bPWHAE+-w_aIoT|+y&A`Cs>*?YcQW5v|3Zo!{0uQs{f&I@9CO$T1 z_btEsInR=bWfGJ6%%}_|mVFJ3A2?VJF|jGc?0dn&(;%-PAZEbu@RO^00>dAM#tjXO z9Mko!7?~fibF{GXIP9po$SJ{K@1UTQz;Nhkx8DJVAB;?ijLZUh@g+=b2lxdzxFs42 zel8L=V5n