123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- /****************************************************************************
- Copyright (c) 2014-2016 Chukong Technologies Inc.
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
- http://www.cocos2d-x.org
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- #include "3d/CCMesh.h"
- #include "3d/CCMeshSkin.h"
- #include "3d/CCSkeleton3D.h"
- #include "3d/CCMeshVertexIndexData.h"
- #include "2d/CCLight.h"
- #include "2d/CCScene.h"
- #include "base/CCEventDispatcher.h"
- #include "base/CCDirector.h"
- #include "base/CCConfiguration.h"
- #include "renderer/CCTextureCache.h"
- #include "renderer/CCGLProgramState.h"
- #include "renderer/CCMaterial.h"
- #include "renderer/CCTechnique.h"
- #include "renderer/CCPass.h"
- #include "renderer/CCRenderer.h"
- #include "renderer/CCVertexAttribBinding.h"
- #include "math/Mat4.h"
- using namespace std;
- NS_CC_BEGIN
- // Helpers
- //sampler uniform names, only diffuse and normal texture are supported for now
- std::string s_uniformSamplerName[] =
- {
- "",//NTextureData::Usage::Unknown,
- "",//NTextureData::Usage::None
- "",//NTextureData::Usage::Diffuse
- "",//NTextureData::Usage::Emissive
- "",//NTextureData::Usage::Ambient
- "",//NTextureData::Usage::Specular
- "",//NTextureData::Usage::Shininess
- "u_normalTex",//NTextureData::Usage::Normal
- "",//NTextureData::Usage::Bump
- "",//NTextureData::Usage::Transparency
- "",//NTextureData::Usage::Reflection
- };
- static const char *s_dirLightUniformColorName = "u_DirLightSourceColor";
- static const char *s_dirLightUniformDirName = "u_DirLightSourceDirection";
- static const char *s_pointLightUniformColorName = "u_PointLightSourceColor";
- static const char *s_pointLightUniformPositionName = "u_PointLightSourcePosition";
- static const char *s_pointLightUniformRangeInverseName = "u_PointLightSourceRangeInverse";
- static const char *s_spotLightUniformColorName = "u_SpotLightSourceColor";
- static const char *s_spotLightUniformPositionName = "u_SpotLightSourcePosition";
- static const char *s_spotLightUniformDirName = "u_SpotLightSourceDirection";
- static const char *s_spotLightUniformInnerAngleCosName = "u_SpotLightSourceInnerAngleCos";
- static const char *s_spotLightUniformOuterAngleCosName = "u_SpotLightSourceOuterAngleCos";
- static const char *s_spotLightUniformRangeInverseName = "u_SpotLightSourceRangeInverse";
- static const char *s_ambientLightUniformColorName = "u_AmbientLightSourceColor";
- // helpers
- void Mesh::resetLightUniformValues()
- {
- const auto& conf = Configuration::getInstance();
- int maxDirLight = conf->getMaxSupportDirLightInShader();
- int maxPointLight = conf->getMaxSupportPointLightInShader();
- int maxSpotLight = conf->getMaxSupportSpotLightInShader();
- _dirLightUniformColorValues.assign(maxDirLight, Vec3::ZERO);
- _dirLightUniformDirValues.assign(maxDirLight, Vec3::ZERO);
- _pointLightUniformColorValues.assign(maxPointLight, Vec3::ZERO);
- _pointLightUniformPositionValues.assign(maxPointLight, Vec3::ZERO);
- _pointLightUniformRangeInverseValues.assign(maxPointLight, 0.0f);
- _spotLightUniformColorValues.assign(maxSpotLight, Vec3::ZERO);
- _spotLightUniformPositionValues.assign(maxSpotLight, Vec3::ZERO);
- _spotLightUniformDirValues.assign(maxSpotLight, Vec3::ZERO);
- _spotLightUniformInnerAngleCosValues.assign(maxSpotLight, 1.0f);
- _spotLightUniformOuterAngleCosValues.assign(maxSpotLight, 0.0f);
- _spotLightUniformRangeInverseValues.assign(maxSpotLight, 0.0f);
- }
- //Generate a dummy texture when the texture file is missing
- static Texture2D * getDummyTexture()
- {
- auto texture = Director::getInstance()->getTextureCache()->getTextureForKey("/dummyTexture");
- if(!texture)
- {
- #ifdef NDEBUG
- unsigned char data[] ={0,0,0,0};//1*1 transparent picture
- #else
- unsigned char data[] ={255,0,0,255};//1*1 red picture
- #endif
- Image * image =new (std::nothrow) Image();
- image->initWithRawData(data,sizeof(data),1,1,sizeof(unsigned char));
- texture=Director::getInstance()->getTextureCache()->addImage(image,"/dummyTexture");
- image->release();
- }
- return texture;
- }
- Mesh::Mesh()
- : _skin(nullptr)
- , _visible(true)
- , _isTransparent(false)
- , _force2DQueue(false)
- , _meshIndexData(nullptr)
- , _glProgramState(nullptr)
- , _blend(BlendFunc::ALPHA_NON_PREMULTIPLIED)
- , _blendDirty(true)
- , _material(nullptr)
- , _texFile("")
- {
-
- }
- Mesh::~Mesh()
- {
- for (auto &tex : _textures){
- CC_SAFE_RELEASE(tex.second);
- }
- CC_SAFE_RELEASE(_skin);
- CC_SAFE_RELEASE(_meshIndexData);
- CC_SAFE_RELEASE(_material);
- CC_SAFE_RELEASE(_glProgramState);
- }
- GLuint Mesh::getVertexBuffer() const
- {
- return _meshIndexData->getVertexBuffer()->getVBO();
- }
- bool Mesh::hasVertexAttrib(int attrib) const
- {
- return _meshIndexData->getMeshVertexData()->hasVertexAttrib(attrib);
- }
- ssize_t Mesh::getMeshVertexAttribCount() const
- {
- return _meshIndexData->getMeshVertexData()->getMeshVertexAttribCount();
- }
- const MeshVertexAttrib& Mesh::getMeshVertexAttribute(int idx)
- {
- return _meshIndexData->getMeshVertexData()->getMeshVertexAttrib(idx);
- }
- int Mesh::getVertexSizeInBytes() const
- {
- return _meshIndexData->getVertexBuffer()->getSizePerVertex();
- }
- Mesh* Mesh::create(const std::vector<float>& positions, const std::vector<float>& normals, const std::vector<float>& texs, const IndexArray& indices)
- {
- int perVertexSizeInFloat = 0;
- std::vector<float> vertices;
- std::vector<MeshVertexAttrib> attribs;
- MeshVertexAttrib att;
- att.size = 3;
- att.type = GL_FLOAT;
- att.attribSizeBytes = att.size * sizeof(float);
-
- if (positions.size())
- {
- perVertexSizeInFloat += 3;
- att.vertexAttrib = GLProgram::VERTEX_ATTRIB_POSITION;
- attribs.push_back(att);
- }
- if (normals.size())
- {
- perVertexSizeInFloat += 3;
- att.vertexAttrib = GLProgram::VERTEX_ATTRIB_NORMAL;
- attribs.push_back(att);
- }
- if (texs.size())
- {
- perVertexSizeInFloat += 2;
- att.vertexAttrib = GLProgram::VERTEX_ATTRIB_TEX_COORD;
- att.size = 2;
- att.attribSizeBytes = att.size * sizeof(float);
- attribs.push_back(att);
- }
-
- bool hasNormal = (normals.size() != 0);
- bool hasTexCoord = (texs.size() != 0);
- //position, normal, texCoordinate into _vertexs
- size_t vertexNum = positions.size() / 3;
- for(size_t i = 0; i < vertexNum; i++)
- {
- vertices.push_back(positions[i * 3]);
- vertices.push_back(positions[i * 3 + 1]);
- vertices.push_back(positions[i * 3 + 2]);
- if (hasNormal)
- {
- vertices.push_back(normals[i * 3]);
- vertices.push_back(normals[i * 3 + 1]);
- vertices.push_back(normals[i * 3 + 2]);
- }
-
- if (hasTexCoord)
- {
- vertices.push_back(texs[i * 2]);
- vertices.push_back(texs[i * 2 + 1]);
- }
- }
- return create(vertices, perVertexSizeInFloat, indices, attribs);
- }
- Mesh* Mesh::create(const std::vector<float>& vertices, int /*perVertexSizeInFloat*/, const IndexArray& indices, const std::vector<MeshVertexAttrib>& attribs)
- {
- MeshData meshdata;
- meshdata.attribs = attribs;
- meshdata.vertex = vertices;
- meshdata.subMeshIndices.push_back(indices);
- meshdata.subMeshIds.push_back("");
- auto meshvertexdata = MeshVertexData::create(meshdata);
- auto indexData = meshvertexdata->getMeshIndexDataByIndex(0);
-
- return create("", indexData);
- }
- Mesh* Mesh::create(const std::string& name, MeshIndexData* indexData, MeshSkin* skin)
- {
- auto state = new (std::nothrow) Mesh();
- state->autorelease();
- state->bindMeshCommand();
- state->_name = name;
- state->setMeshIndexData(indexData);
- state->setSkin(skin);
-
- return state;
- }
- void Mesh::setVisible(bool visible)
- {
- if (_visible != visible)
- {
- _visible = visible;
- if (_visibleChanged)
- _visibleChanged();
- }
- }
- bool Mesh::isVisible() const
- {
- return _visible;
- }
- void Mesh::setTexture(const std::string& texPath)
- {
- _texFile = texPath;
- auto tex = Director::getInstance()->getTextureCache()->addImage(texPath);
- setTexture(tex, NTextureData::Usage::Diffuse);
- }
- void Mesh::setTexture(Texture2D* tex)
- {
- setTexture(tex, NTextureData::Usage::Diffuse);
- }
- void Mesh::setTexture(Texture2D* tex, NTextureData::Usage usage, bool cacheFileName)
- {
- // Texture must be saved for future use
- // it doesn't matter if the material is already set or not
- // This functionality is added for compatibility issues
- if (tex == nullptr)
- tex = getDummyTexture();
-
- CC_SAFE_RETAIN(tex);
- CC_SAFE_RELEASE(_textures[usage]);
- _textures[usage] = tex;
-
- if (usage == NTextureData::Usage::Diffuse){
- if (_material) {
- auto technique = _material->_currentTechnique;
- for(auto& pass: technique->_passes)
- {
- // FIXME: Ideally it should use glProgramState->setUniformTexture()
- // and set CC_Texture0 that way. But trying to it, will trigger
- // another bug
- pass->setTexture(tex);
- }
- }
-
- bindMeshCommand();
- if (cacheFileName)
- _texFile = tex->getPath();
- }
- else if (usage == NTextureData::Usage::Normal) // currently only diffuse and normal are supported
- {
- if (_material){
- auto technique = _material->_currentTechnique;
- for(auto& pass: technique->_passes)
- {
- pass->getGLProgramState()->setUniformTexture(s_uniformSamplerName[(int)usage], tex);
- }
- }
- }
- }
- void Mesh::setTexture(const std::string& texPath, NTextureData::Usage usage)
- {
- auto tex = Director::getInstance()->getTextureCache()->addImage(texPath);
- setTexture(tex, usage);
- }
- Texture2D* Mesh::getTexture() const
- {
- return _textures.at(NTextureData::Usage::Diffuse);
- }
- Texture2D* Mesh::getTexture(NTextureData::Usage usage)
- {
- return _textures[usage];
- }
- void Mesh::setMaterial(Material* material)
- {
- if (_material != material) {
- CC_SAFE_RELEASE(_material);
- _material = material;
- CC_SAFE_RETAIN(_material);
- }
- if (_material)
- {
- for (auto technique: _material->getTechniques())
- {
- for (auto pass: technique->getPasses())
- {
- auto vertexAttribBinding = VertexAttribBinding::create(_meshIndexData, pass->getGLProgramState());
- pass->setVertexAttribBinding(vertexAttribBinding);
- }
- }
- }
- // Was the texture set before the GLProgramState ? Set it
- for(auto& tex : _textures)
- setTexture(tex.second, tex.first);
-
-
- if (_blendDirty)
- setBlendFunc(_blend);
-
- bindMeshCommand();
- }
- Material* Mesh::getMaterial() const
- {
- return _material;
- }
- void Mesh::draw(Renderer* renderer, float globalZOrder, const Mat4& transform, uint32_t flags, unsigned int lightMask, const Vec4& color, bool forceDepthWrite)
- {
- if (! isVisible())
- return;
- bool isTransparent = (_isTransparent || color.w < 1.f);
- float globalZ = isTransparent ? 0 : globalZOrder;
- if (isTransparent)
- flags |= Node::FLAGS_RENDER_AS_3D;
- _meshCommand.init(globalZ,
- _material,
- getVertexBuffer(),
- getIndexBuffer(),
- getPrimitiveType(),
- getIndexFormat(),
- getIndexCount(),
- transform,
- flags);
- if (isTransparent && !forceDepthWrite)
- _material->getStateBlock()->setDepthWrite(false);
- else
- _material->getStateBlock()->setDepthWrite(true);
- _meshCommand.setSkipBatching(isTransparent);
- _meshCommand.setTransparent(isTransparent);
- _meshCommand.set3D(!_force2DQueue);
- _material->getStateBlock()->setBlend(_force2DQueue || isTransparent);
- // set default uniforms for Mesh
- // 'u_color' and others
- const auto scene = Director::getInstance()->getRunningScene();
- auto technique = _material->_currentTechnique;
- for(const auto pass : technique->_passes)
- {
- auto programState = pass->getGLProgramState();
- programState->setUniformVec4("u_color", color);
- if (_skin)
- programState->setUniformVec4v("u_matrixPalette", (GLsizei)_skin->getMatrixPaletteSize(), _skin->getMatrixPalette());
- if (scene && scene->getLights().size() > 0)
- setLightUniforms(pass, scene, color, lightMask);
- }
- renderer->addCommand(&_meshCommand);
- }
- void Mesh::setSkin(MeshSkin* skin)
- {
- if (_skin != skin)
- {
- CC_SAFE_RETAIN(skin);
- CC_SAFE_RELEASE(_skin);
- _skin = skin;
- calculateAABB();
- }
- }
- void Mesh::setMeshIndexData(MeshIndexData* subMesh)
- {
- if (_meshIndexData != subMesh)
- {
- CC_SAFE_RETAIN(subMesh);
- CC_SAFE_RELEASE(_meshIndexData);
- _meshIndexData = subMesh;
- calculateAABB();
- bindMeshCommand();
- }
- }
- void Mesh::setGLProgramState(GLProgramState* glProgramState)
- {
- // XXX create dummy texture
- auto material = Material::createWithGLStateProgram(glProgramState);
- if (_material)
- material->setStateBlock(_material->getStateBlock());
- setMaterial(material);
- }
- GLProgramState* Mesh::getGLProgramState() const
- {
- return _material ?
- _material->_currentTechnique->_passes.at(0)->getGLProgramState()
- : nullptr;
- }
- void Mesh::calculateAABB()
- {
- if (_meshIndexData)
- {
- _aabb = _meshIndexData->getAABB();
- if (_skin)
- {
- //get skin root
- Bone3D* root = nullptr;
- Mat4 invBindPose;
- if (_skin->_skinBones.size())
- {
- root = _skin->_skinBones.at(0);
- while (root) {
- auto parent = root->getParentBone();
- bool parentInSkinBone = false;
- for (const auto& bone : _skin->_skinBones) {
- if (bone == parent)
- {
- parentInSkinBone = true;
- break;
- }
- }
- if (!parentInSkinBone)
- break;
- root = parent;
- }
- }
-
- if (root)
- {
- _aabb.transform(root->getWorldMat() * _skin->getInvBindPose(root));
- }
- }
- }
- }
- void Mesh::bindMeshCommand()
- {
- if (_material && _meshIndexData)
- {
- auto pass = _material->_currentTechnique->_passes.at(0);
- auto glprogramstate = pass->getGLProgramState();
- auto texture = pass->getTexture();
- auto textureid = texture ? texture->getName() : 0;
- // XXX
- // auto blend = pass->getStateBlock()->getBlendFunc();
- auto blend = BlendFunc::ALPHA_PREMULTIPLIED;
- _meshCommand.genMaterialID(textureid, glprogramstate, _meshIndexData->getVertexBuffer()->getVBO(), _meshIndexData->getIndexBuffer()->getVBO(), blend);
- _material->getStateBlock()->setCullFace(true);
- _material->getStateBlock()->setDepthTest(true);
- }
- }
- void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigned int lightmask)
- {
- CCASSERT(pass, "Invalid Pass");
- CCASSERT(scene, "Invalid scene");
- const auto& conf = Configuration::getInstance();
- int maxDirLight = conf->getMaxSupportDirLightInShader();
- int maxPointLight = conf->getMaxSupportPointLightInShader();
- int maxSpotLight = conf->getMaxSupportSpotLightInShader();
- auto &lights = scene->getLights();
- auto glProgramState = pass->getGLProgramState();
- auto attributes = pass->getVertexAttributeBinding()->getVertexAttribsFlags();
- if (attributes & (1 << GLProgram::VERTEX_ATTRIB_NORMAL))
- {
- resetLightUniformValues();
- GLint enabledDirLightNum = 0;
- GLint enabledPointLightNum = 0;
- GLint enabledSpotLightNum = 0;
- Vec3 ambientColor;
- for (const auto& light : lights)
- {
- bool useLight = light->isEnabled() && ((unsigned int)light->getLightFlag() & lightmask);
- if (useLight)
- {
- float intensity = light->getIntensity();
- switch (light->getLightType())
- {
- case LightType::DIRECTIONAL:
- {
- if(enabledDirLightNum < maxDirLight)
- {
- auto dirLight = static_cast<DirectionLight *>(light);
- Vec3 dir = dirLight->getDirectionInWorld();
- dir.normalize();
- const Color3B &col = dirLight->getDisplayedColor();
- _dirLightUniformColorValues[enabledDirLightNum].set(col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
- _dirLightUniformDirValues[enabledDirLightNum] = dir;
- ++enabledDirLightNum;
- }
- }
- break;
- case LightType::POINT:
- {
- if(enabledPointLightNum < maxPointLight)
- {
- auto pointLight = static_cast<PointLight *>(light);
- Mat4 mat= pointLight->getNodeToWorldTransform();
- const Color3B &col = pointLight->getDisplayedColor();
- _pointLightUniformColorValues[enabledPointLightNum].set(col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
- _pointLightUniformPositionValues[enabledPointLightNum].set(mat.m[12], mat.m[13], mat.m[14]);
- _pointLightUniformRangeInverseValues[enabledPointLightNum] = 1.0f / pointLight->getRange();
- ++enabledPointLightNum;
- }
- }
- break;
- case LightType::SPOT:
- {
- if(enabledSpotLightNum < maxSpotLight)
- {
- auto spotLight = static_cast<SpotLight *>(light);
- Vec3 dir = spotLight->getDirectionInWorld();
- dir.normalize();
- Mat4 mat= light->getNodeToWorldTransform();
- const Color3B &col = spotLight->getDisplayedColor();
- _spotLightUniformColorValues[enabledSpotLightNum].set(col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
- _spotLightUniformPositionValues[enabledSpotLightNum].set(mat.m[12], mat.m[13], mat.m[14]);
- _spotLightUniformDirValues[enabledSpotLightNum] = dir;
- _spotLightUniformInnerAngleCosValues[enabledSpotLightNum] = spotLight->getCosInnerAngle();
- _spotLightUniformOuterAngleCosValues[enabledSpotLightNum] = spotLight->getCosOuterAngle();
- _spotLightUniformRangeInverseValues[enabledSpotLightNum] = 1.0f / spotLight->getRange();
- ++enabledSpotLightNum;
- }
- }
- break;
- case LightType::AMBIENT:
- {
- auto ambLight = static_cast<AmbientLight *>(light);
- const Color3B &col = ambLight->getDisplayedColor();
- ambientColor.add(col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity);
- }
- break;
- default:
- break;
- }
- }
- }
- if (0 < maxDirLight)
- {
- glProgramState->setUniformVec3v(s_dirLightUniformColorName, _dirLightUniformColorValues.size(), &_dirLightUniformColorValues[0]);
- glProgramState->setUniformVec3v(s_dirLightUniformDirName, _dirLightUniformDirValues.size(), &_dirLightUniformDirValues[0]);
- }
- if (0 < maxPointLight)
- {
- glProgramState->setUniformVec3v(s_pointLightUniformColorName, _pointLightUniformColorValues.size(), &_pointLightUniformColorValues[0]);
- glProgramState->setUniformVec3v(s_pointLightUniformPositionName, _pointLightUniformPositionValues.size(), &_pointLightUniformPositionValues[0]);
- glProgramState->setUniformFloatv(s_pointLightUniformRangeInverseName, _pointLightUniformRangeInverseValues.size(), &_pointLightUniformRangeInverseValues[0]);
- }
- if (0 < maxSpotLight)
- {
- glProgramState->setUniformVec3v(s_spotLightUniformColorName, _spotLightUniformColorValues.size(), &_spotLightUniformColorValues[0]);
- glProgramState->setUniformVec3v(s_spotLightUniformPositionName, _spotLightUniformPositionValues.size(), &_spotLightUniformPositionValues[0]);
- glProgramState->setUniformVec3v(s_spotLightUniformDirName, _spotLightUniformDirValues.size(), &_spotLightUniformDirValues[0]);
- glProgramState->setUniformFloatv(s_spotLightUniformInnerAngleCosName, _spotLightUniformInnerAngleCosValues.size(), &_spotLightUniformInnerAngleCosValues[0]);
- glProgramState->setUniformFloatv(s_spotLightUniformOuterAngleCosName, _spotLightUniformOuterAngleCosValues.size(), &_spotLightUniformOuterAngleCosValues[0]);
- glProgramState->setUniformFloatv(s_spotLightUniformRangeInverseName, _spotLightUniformRangeInverseValues.size(), &_spotLightUniformRangeInverseValues[0]);
- }
- glProgramState->setUniformVec3(s_ambientLightUniformColorName, Vec3(ambientColor.x, ambientColor.y, ambientColor.z));
- }
- else // normal does not exist
- {
- Vec3 ambient(0.0f, 0.0f, 0.0f);
- bool hasAmbient = false;
- for (const auto& light : lights)
- {
- if (light->getLightType() == LightType::AMBIENT)
- {
- bool useLight = light->isEnabled() && ((unsigned int)light->getLightFlag() & lightmask);
- if (useLight)
- {
- hasAmbient = true;
- const Color3B &col = light->getDisplayedColor();
- ambient.x += col.r * light->getIntensity();
- ambient.y += col.g * light->getIntensity();
- ambient.z += col.b * light->getIntensity();
- }
- }
- }
- if (hasAmbient)
- {
- ambient.x /= 255.f; ambient.y /= 255.f; ambient.z /= 255.f;
- //override the uniform value of u_color using the calculated color
- glProgramState->setUniformVec4("u_color", Vec4(color.x * ambient.x, color.y * ambient.y, color.z * ambient.z, color.w));
- }
- }
- }
- void Mesh::setBlendFunc(const BlendFunc &blendFunc)
- {
- // Blend must be saved for future use
- // it doesn't matter if the material is already set or not
- // This functionality is added for compatibility issues
- if(_blend != blendFunc)
- {
- _blendDirty = true;
- _blend = blendFunc;
- }
- if (_material) {
- _material->getStateBlock()->setBlendFunc(blendFunc);
- bindMeshCommand();
- }
- }
- const BlendFunc& Mesh::getBlendFunc() const
- {
- // return _material->_currentTechnique->_passes.at(0)->getBlendFunc();
- return _blend;
- }
- GLenum Mesh::getPrimitiveType() const
- {
- return _meshIndexData->getPrimitiveType();
- }
- ssize_t Mesh::getIndexCount() const
- {
- return _meshIndexData->getIndexBuffer()->getIndexNumber();
- }
- GLenum Mesh::getIndexFormat() const
- {
- return GL_UNSIGNED_SHORT;
- }
- GLuint Mesh::getIndexBuffer() const
- {
- return _meshIndexData->getIndexBuffer()->getVBO();
- }
- NS_CC_END
|