diff --git a/cocos/3d/CCLight3D.h b/cocos/3d/CCLight3D.h index 3486d59fc6..16985b5825 100644 --- a/cocos/3d/CCLight3D.h +++ b/cocos/3d/CCLight3D.h @@ -30,6 +30,11 @@ NS_CC_BEGIN +#define CC_MAX_DIRECTIONAL_LIGHT_NUM 1 +#define CC_MAX_POINT_LIGHT_NUM 1 +#define CC_MAX_SPOT_LIGHT_NUM 1 +#define CC_MAX_AMBIENT_LIGHT_NUM 1 + enum class LightType { DIRECTIONAL = 0, diff --git a/cocos/renderer/CCGLProgram.cpp b/cocos/renderer/CCGLProgram.cpp index 9d94fe0383..0ef6c14bf2 100644 --- a/cocos/renderer/CCGLProgram.cpp +++ b/cocos/renderer/CCGLProgram.cpp @@ -44,11 +44,6 @@ THE SOFTWARE. #include "CCPrecompiledShaders.h" #endif -#define CC_MAX_DIRECTIONAL_LIGHT_NUM 1 -#define CC_MAX_POINT_LIGHT_NUM 1 -#define CC_MAX_SPOT_LIGHT_NUM 1 -#define CC_MAX_AMBIENT_LIGHT_NUM 1 - NS_CC_BEGIN typedef struct _hashUniformEntry @@ -553,10 +548,6 @@ void GLProgram::updateUniforms() _builtInUniforms[UNIFORM_SAMPLER2] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER2); _builtInUniforms[UNIFORM_SAMPLER3] = glGetUniformLocation(_program, UNIFORM_NAME_SAMPLER3); - _flags.usesLights = (0 < CC_MAX_DIRECTIONAL_LIGHT_NUM) || - (0 < CC_MAX_POINT_LIGHT_NUM) || - (0 < CC_MAX_SPOT_LIGHT_NUM) || - (0 < CC_MAX_AMBIENT_LIGHT_NUM); _flags.usesP = _builtInUniforms[UNIFORM_P_MATRIX] != -1; _flags.usesMV = _builtInUniforms[UNIFORM_MV_MATRIX] != -1; _flags.usesMVP = _builtInUniforms[UNIFORM_MVP_MATRIX] != -1; @@ -965,101 +956,6 @@ void GLProgram::setUniformsForBuiltins(const Mat4 &matrixMV) if(_flags.usesRandom) setUniformLocationWith4f(_builtInUniforms[GLProgram::UNIFORM_RANDOM01], CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1(), CCRANDOM_0_1()); - - if (_flags.usesLights) - { - Director *director = Director::getInstance(); - auto scene = director->getRunningScene(); - if (scene) - { - auto &lights = scene->getLights(); - char str[64]; - GLint enabledDirLightNum = 0; - GLint enabledPointLightNum = 0; - GLint enabledSpotLightNum = 0; - GLint enabledAmbientLightNum = 0; - for (unsigned int i = 0; i < lights.size(); ++i) - { - BaseLight3D *light = lights[i]; - float intensity = light->isEnabled() == true? light->getIntensity() : 0.0f; - switch (light->getLightType()) - { - case LightType::DIRECTIONAL: - { - CCASSERT(enabledDirLightNum < CC_MAX_DIRECTIONAL_LIGHT_NUM, ""); - DirectionLight3D *dirLight = static_cast(light); - Vec3 dir = dirLight->getDirectionInWorld(); - dir.normalize(); - const Color3B &col = dirLight->getDisplayedColor(); - sprintf(str, "CC_DirLightSourceColor[%d]", enabledDirLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); - sprintf(str, "CC_DirLightSourceDirection[%d]", enabledDirLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), dir.x, dir.y, dir.z); - sprintf(str, "CC_DirLightSourceIntensity[%d]", enabledDirLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), intensity); - ++enabledDirLightNum; - } - break; - case LightType::POINT: - { - CCASSERT(enabledPointLightNum < CC_MAX_POINT_LIGHT_NUM, ""); - PointLight3D *pointLight = static_cast(light); - Mat4 mat= pointLight->getNodeToWorldTransform(); - const Color3B &col = pointLight->getDisplayedColor(); - sprintf(str, "CC_PointLightSourceColor[%d]", enabledPointLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); - sprintf(str, "CC_PointLightSourcePosition[%d]", enabledPointLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), mat.m[12], mat.m[13], mat.m[14]); - sprintf(str, "CC_PointLightSourceRangeInverse[%d]", enabledPointLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), 1.0f / pointLight->getRange()); - sprintf(str, "CC_PointLightSourceIntensity[%d]", enabledPointLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), intensity); - ++enabledPointLightNum; - } - break; - case LightType::SPOT: - { - CCASSERT(enabledSpotLightNum < CC_MAX_SPOT_LIGHT_NUM, ""); - SpotLight3D *spotLight = static_cast(light); - Vec3 dir = spotLight->getDirectionInWorld(); - dir.normalize(); - Mat4 mat= light->getNodeToWorldTransform(); - const Color3B &col = spotLight->getDisplayedColor(); - sprintf(str, "CC_SpotLightSourceColor[%d]", enabledSpotLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); - sprintf(str, "CC_SpotLightSourcePosition[%d]", enabledSpotLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), mat.m[12], mat.m[13], mat.m[14]); - sprintf(str, "CC_SpotLightSourceDirection[%d]", enabledSpotLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), dir.x, dir.y, dir.z); - sprintf(str, "CC_SpotLightSourceInnerAngleCos[%d]", enabledSpotLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), spotLight->getCosInnerAngle()); - sprintf(str, "CC_SpotLightSourceOuterAngleCos[%d]", enabledSpotLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), spotLight->getCosOuterAngle()); - sprintf(str, "CC_SpotLightSourceRangeInverse[%d]", enabledSpotLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), 1.0f / spotLight->getRange()); - sprintf(str, "CC_SpotLightSourceIntensity[%d]", enabledSpotLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), intensity); - ++enabledSpotLightNum; - } - break; - case LightType::AMBIENT: - { - CCASSERT(enabledAmbientLightNum < CC_MAX_AMBIENT_LIGHT_NUM, ""); - AmbientLight3D *ambLight = static_cast(light); - const Color3B &col = ambLight->getDisplayedColor(); - sprintf(str, "CC_AmbientLightSourceColor[%d]", enabledAmbientLightNum); - setUniformLocationWith3f(glGetUniformLocation(_program, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); - sprintf(str, "CC_AmbientLightSourceIntensity[%d]", enabledAmbientLightNum); - setUniformLocationWith1f(glGetUniformLocation(_program, str), intensity); - ++enabledAmbientLightNum; - } - break; - default: - break; - } - } - } - } } void GLProgram::reset() diff --git a/cocos/renderer/CCGLProgram.h b/cocos/renderer/CCGLProgram.h index b56736af81..830ca8b487 100644 --- a/cocos/renderer/CCGLProgram.h +++ b/cocos/renderer/CCGLProgram.h @@ -363,7 +363,6 @@ protected: unsigned int usesMV:1; unsigned int usesP:1; unsigned int usesRandom:1; - unsigned int usesLights:1; // handy way to initialize the bitfield flag_struct() { memset(this, 0, sizeof(*this)); } } _flags; diff --git a/cocos/renderer/CCMeshCommand.cpp b/cocos/renderer/CCMeshCommand.cpp index 6873e29ff2..b4eb1a22d7 100644 --- a/cocos/renderer/CCMeshCommand.cpp +++ b/cocos/renderer/CCMeshCommand.cpp @@ -36,6 +36,7 @@ #include "renderer/CCTextureAtlas.h" #include "renderer/CCTexture2D.h" #include "renderer/ccGLStateCache.h" +#include "3d/CCLight3D.h" #include "xxhash.h" NS_CC_BEGIN @@ -59,6 +60,7 @@ MeshCommand::MeshCommand() , _matrixPaletteSize(0) , _materialID(0) , _vao(0) +, _useLights(false) { _type = RenderCommand::Type::MESH_COMMAND; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8) @@ -92,6 +94,11 @@ void MeshCommand::init(float globalOrder, _indexFormat = indexFormat; _indexCount = indexCount; _mv.set(mv); + + _useLights = (0 < CC_MAX_DIRECTIONAL_LIGHT_NUM) || + (0 < CC_MAX_POINT_LIGHT_NUM) || + (0 < CC_MAX_SPOT_LIGHT_NUM) || + (0 < CC_MAX_AMBIENT_LIGHT_NUM); } void MeshCommand::setCullFaceEnabled(bool enable) @@ -222,6 +229,11 @@ void MeshCommand::batchDraw() _glProgramState->applyGLProgram(_mv); _glProgramState->applyUniforms(); + + if (_useLights) + { + applyLightUniforms(); + } // Draw glDrawElements(_primitive, (GLsizei)_indexCount, _indexFormat, 0); @@ -262,6 +274,11 @@ void MeshCommand::execute() _glProgramState->apply(_mv); + if (_useLights) + { + applyLightUniforms(); + } + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer); // Draw @@ -306,11 +323,110 @@ void MeshCommand::releaseVAO() } } + +void MeshCommand::applyLightUniforms() +{ + Director *director = Director::getInstance(); + auto scene = director->getRunningScene(); + if (scene) + { + GLProgram *glProgram = _glProgramState->getGLProgram(); + GLint programID = glProgram->getProgram(); + auto &lights = scene->getLights(); + char str[64]; + GLint enabledDirLightNum = 0; + GLint enabledPointLightNum = 0; + GLint enabledSpotLightNum = 0; + GLint enabledAmbientLightNum = 0; + for (unsigned int i = 0; i < lights.size(); ++i) + { + BaseLight3D *light = lights[i]; + float intensity = light->isEnabled() == true? light->getIntensity() : 0.0f; + switch (light->getLightType()) + { + case LightType::DIRECTIONAL: + { + CCASSERT(enabledDirLightNum < CC_MAX_DIRECTIONAL_LIGHT_NUM, ""); + DirectionLight3D *dirLight = static_cast(light); + Vec3 dir = dirLight->getDirectionInWorld(); + dir.normalize(); + const Color3B &col = dirLight->getDisplayedColor(); + sprintf(str, "CC_DirLightSourceColor[%d]", enabledDirLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); + sprintf(str, "CC_DirLightSourceDirection[%d]", enabledDirLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), dir.x, dir.y, dir.z); + sprintf(str, "CC_DirLightSourceIntensity[%d]", enabledDirLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), intensity); + ++enabledDirLightNum; + } + break; + case LightType::POINT: + { + CCASSERT(enabledPointLightNum < CC_MAX_POINT_LIGHT_NUM, ""); + PointLight3D *pointLight = static_cast(light); + Mat4 mat= pointLight->getNodeToWorldTransform(); + const Color3B &col = pointLight->getDisplayedColor(); + sprintf(str, "CC_PointLightSourceColor[%d]", enabledPointLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); + sprintf(str, "CC_PointLightSourcePosition[%d]", enabledPointLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), mat.m[12], mat.m[13], mat.m[14]); + sprintf(str, "CC_PointLightSourceRangeInverse[%d]", enabledPointLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), 1.0f / pointLight->getRange()); + sprintf(str, "CC_PointLightSourceIntensity[%d]", enabledPointLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), intensity); + ++enabledPointLightNum; + } + break; + case LightType::SPOT: + { + CCASSERT(enabledSpotLightNum < CC_MAX_SPOT_LIGHT_NUM, ""); + SpotLight3D *spotLight = static_cast(light); + Vec3 dir = spotLight->getDirectionInWorld(); + dir.normalize(); + Mat4 mat= light->getNodeToWorldTransform(); + const Color3B &col = spotLight->getDisplayedColor(); + sprintf(str, "CC_SpotLightSourceColor[%d]", enabledSpotLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); + sprintf(str, "CC_SpotLightSourcePosition[%d]", enabledSpotLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), mat.m[12], mat.m[13], mat.m[14]); + sprintf(str, "CC_SpotLightSourceDirection[%d]", enabledSpotLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), dir.x, dir.y, dir.z); + sprintf(str, "CC_SpotLightSourceInnerAngleCos[%d]", enabledSpotLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), spotLight->getCosInnerAngle()); + sprintf(str, "CC_SpotLightSourceOuterAngleCos[%d]", enabledSpotLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), spotLight->getCosOuterAngle()); + sprintf(str, "CC_SpotLightSourceRangeInverse[%d]", enabledSpotLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), 1.0f / spotLight->getRange()); + sprintf(str, "CC_SpotLightSourceIntensity[%d]", enabledSpotLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), intensity); + ++enabledSpotLightNum; + } + break; + case LightType::AMBIENT: + { + CCASSERT(enabledAmbientLightNum < CC_MAX_AMBIENT_LIGHT_NUM, ""); + AmbientLight3D *ambLight = static_cast(light); + const Color3B &col = ambLight->getDisplayedColor(); + sprintf(str, "CC_AmbientLightSourceColor[%d]", enabledAmbientLightNum); + glProgram->setUniformLocationWith3f(glGetUniformLocation(programID, str), col.r / 255.0f, col.g / 255.0f, col.b / 255.0f); + sprintf(str, "CC_AmbientLightSourceIntensity[%d]", enabledAmbientLightNum); + glProgram->setUniformLocationWith1f(glGetUniformLocation(programID, str), intensity); + ++enabledAmbientLightNum; + } + break; + default: + break; + } + } + } +} + #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8) void MeshCommand::listenRendererRecreated(EventCustom* event) { _vao = 0; } + #endif NS_CC_END diff --git a/cocos/renderer/CCMeshCommand.h b/cocos/renderer/CCMeshCommand.h index 094b735e6d..fedea209ae 100644 --- a/cocos/renderer/CCMeshCommand.h +++ b/cocos/renderer/CCMeshCommand.h @@ -84,6 +84,8 @@ protected: // apply renderstate void applyRenderState(); + + void applyLightUniforms(); //restore to all false void restoreRenderState(); @@ -120,6 +122,8 @@ protected: // ModelView transform Mat4 _mv; + + bool _useLights; #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_WP8) EventListenerCustom* _rendererRecreatedListener;