123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- /****************************************************************************
- 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/CCSprite3DMaterial.h"
- #include "3d/CCMesh.h"
- #include "platform/CCFileUtils.h"
- #include "renderer/CCTexture2D.h"
- #include "renderer/CCGLProgram.h"
- #include "renderer/CCGLProgramCache.h"
- #include "renderer/CCGLProgramState.h"
- #include "renderer/CCGLProgramStateCache.h"
- #include "base/CCDirector.h"
- #include "base/CCEventType.h"
- NS_CC_BEGIN
- Sprite3DMaterialCache* Sprite3DMaterialCache::_cacheInstance = nullptr;
- std::unordered_map<std::string, Sprite3DMaterial*> Sprite3DMaterial::_materials;
- Sprite3DMaterial* Sprite3DMaterial::_unLitMaterial = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_unLitNoTexMaterial = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_vertexLitMaterial = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_diffuseMaterial = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_diffuseNoTexMaterial = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_bumpedDiffuseMaterial = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_unLitMaterialSkin = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_vertexLitMaterialSkin = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_diffuseMaterialSkin = nullptr;
- Sprite3DMaterial* Sprite3DMaterial::_bumpedDiffuseMaterialSkin = nullptr;
- void Sprite3DMaterial::createBuiltInMaterial()
- {
- releaseBuiltInMaterial();
-
- auto glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_SKINPOSITION_TEXTURE);
- auto glprogramstate = GLProgramState::create(glProgram);
- _unLitMaterialSkin = new (std::nothrow) Sprite3DMaterial();
- if (_unLitMaterialSkin && _unLitMaterialSkin->initWithGLProgramState(glprogramstate))
- {
- _unLitMaterialSkin->_type = Sprite3DMaterial::MaterialType::UNLIT;
- }
-
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_SKINPOSITION_NORMAL_TEXTURE);
- glprogramstate = GLProgramState::create(glProgram);
- _diffuseMaterialSkin = new (std::nothrow) Sprite3DMaterial();
- if (_diffuseMaterialSkin && _diffuseMaterialSkin->initWithGLProgramState(glprogramstate))
- {
- _diffuseMaterialSkin->_type = Sprite3DMaterial::MaterialType::DIFFUSE;
- }
-
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_POSITION_NORMAL_TEXTURE);
- glprogramstate = GLProgramState::create(glProgram);
- _diffuseMaterial = new (std::nothrow) Sprite3DMaterial();
- if (_diffuseMaterial && _diffuseMaterial->initWithGLProgramState(glprogramstate))
- {
- _diffuseMaterial->_type = Sprite3DMaterial::MaterialType::DIFFUSE;
- }
-
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_POSITION_TEXTURE);
- glprogramstate = GLProgramState::create(glProgram);
- _unLitMaterial = new (std::nothrow) Sprite3DMaterial();
- if (_unLitMaterial && _unLitMaterial->initWithGLProgramState(glprogramstate))
- {
- _unLitMaterial->_type = Sprite3DMaterial::MaterialType::UNLIT;
- }
-
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_POSITION);
- glprogramstate = GLProgramState::create(glProgram);
- _unLitNoTexMaterial = new (std::nothrow) Sprite3DMaterial();
- if (_unLitNoTexMaterial && _unLitNoTexMaterial->initWithGLProgramState(glprogramstate))
- {
- _unLitNoTexMaterial->_type = Sprite3DMaterial::MaterialType::UNLIT_NOTEX;
- }
-
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_POSITION_NORMAL);
- glprogramstate = GLProgramState::create(glProgram);
- _diffuseNoTexMaterial = new (std::nothrow) Sprite3DMaterial();
- if (_diffuseNoTexMaterial && _diffuseNoTexMaterial->initWithGLProgramState(glprogramstate))
- {
- _diffuseNoTexMaterial->_type = Sprite3DMaterial::MaterialType::DIFFUSE_NOTEX;
- }
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_POSITION_BUMPEDNORMAL_TEXTURE);
- glprogramstate = GLProgramState::create(glProgram);
- _bumpedDiffuseMaterial = new (std::nothrow) Sprite3DMaterial();
- if (_bumpedDiffuseMaterial && _bumpedDiffuseMaterial->initWithGLProgramState(glprogramstate))
- {
- _bumpedDiffuseMaterial->_type = Sprite3DMaterial::MaterialType::BUMPED_DIFFUSE;
- }
- glProgram = GLProgramCache::getInstance()->getGLProgram(GLProgram::SHADER_3D_SKINPOSITION_BUMPEDNORMAL_TEXTURE);
- glprogramstate = GLProgramState::create(glProgram);
- _bumpedDiffuseMaterialSkin = new (std::nothrow) Sprite3DMaterial();
- if (_bumpedDiffuseMaterialSkin && _bumpedDiffuseMaterialSkin->initWithGLProgramState(glprogramstate))
- {
- _bumpedDiffuseMaterialSkin->_type = Sprite3DMaterial::MaterialType::BUMPED_DIFFUSE;
- }
- }
- void Sprite3DMaterial::releaseBuiltInMaterial()
- {
- CC_SAFE_RELEASE_NULL(_unLitMaterial);
- CC_SAFE_RELEASE_NULL(_unLitMaterialSkin);
-
- CC_SAFE_RELEASE_NULL(_unLitNoTexMaterial);
- CC_SAFE_RELEASE_NULL(_vertexLitMaterial);
- CC_SAFE_RELEASE_NULL(_diffuseMaterial);
- CC_SAFE_RELEASE_NULL(_diffuseNoTexMaterial);
- CC_SAFE_RELEASE_NULL(_bumpedDiffuseMaterial);
-
- CC_SAFE_RELEASE_NULL(_vertexLitMaterialSkin);
- CC_SAFE_RELEASE_NULL(_diffuseMaterialSkin);
- CC_SAFE_RELEASE_NULL(_bumpedDiffuseMaterialSkin);
- }
- void Sprite3DMaterial::releaseCachedMaterial()
- {
- for (auto& it : _materials) {
- if (it.second)
- it.second->release();
- }
- _materials.clear();
- }
- Material* Sprite3DMaterial::clone() const
- {
- auto material = new (std::nothrow) Sprite3DMaterial();
- if (material)
- {
- RenderState::cloneInto(material);
-
- for (const auto& technique: _techniques)
- {
- auto t = technique->clone();
- t->setParent(material);
- for (ssize_t i = 0; i < t->getPassCount(); i++) {
- t->getPassByIndex(i)->setParent(t);
- }
- material->_techniques.pushBack(t);
- }
-
- // current technique
- auto name = _currentTechnique->getName();
- material->_currentTechnique = material->getTechniqueByName(name);
- material->_type = _type;
- material->autorelease();
- }
- return material;
- }
- Sprite3DMaterial* Sprite3DMaterial::createBuiltInMaterial(MaterialType type, bool skinned)
- {
- /////
- if (_diffuseMaterial == nullptr)
- createBuiltInMaterial();
-
- Sprite3DMaterial* material = nullptr;
- switch (type) {
- case Sprite3DMaterial::MaterialType::UNLIT:
- material = skinned ? _unLitMaterialSkin : _unLitMaterial;
- break;
-
- case Sprite3DMaterial::MaterialType::UNLIT_NOTEX:
- material = _unLitNoTexMaterial;
- break;
-
- case Sprite3DMaterial::MaterialType::VERTEX_LIT:
- CCASSERT(0, "not implement");
- break;
-
- case Sprite3DMaterial::MaterialType::DIFFUSE:
- material = skinned ? _diffuseMaterialSkin : _diffuseMaterial;
- break;
-
- case Sprite3DMaterial::MaterialType::DIFFUSE_NOTEX:
- material = _diffuseNoTexMaterial;
- break;
-
- case Sprite3DMaterial::MaterialType::BUMPED_DIFFUSE:
- material = skinned ? _bumpedDiffuseMaterialSkin : _bumpedDiffuseMaterial;
- break;
-
- default:
- break;
- }
- if (material)
- return (Sprite3DMaterial*)material->clone();
-
- return nullptr;
- }
- Sprite3DMaterial* Sprite3DMaterial::createWithFilename(const std::string& path)
- {
- auto validfilename = FileUtils::getInstance()->fullPathForFilename(path);
- if (validfilename.size() > 0) {
- auto it = _materials.find(validfilename);
- if (it != _materials.end())
- return (Sprite3DMaterial*)it->second->clone();
-
- auto material = new (std::nothrow) Sprite3DMaterial();
- if (material->initWithFile(path))
- {
- material->_type = Sprite3DMaterial::MaterialType::CUSTOM;
- _materials[validfilename] = material;
-
- return (Sprite3DMaterial*)material->clone();
- }
- CC_SAFE_DELETE(material);
- }
- return nullptr;
- }
- Sprite3DMaterial* Sprite3DMaterial::createWithGLStateProgram(GLProgramState* programState)
- {
- CCASSERT(programState, "Invalid GL Program State");
-
- auto mat = new (std::nothrow) Sprite3DMaterial();
- if (mat && mat->initWithGLProgramState(programState))
- {
- mat->_type = Sprite3DMaterial::MaterialType::CUSTOM;
- mat->autorelease();
- return mat;
-
- }
- CC_SAFE_DELETE(mat);
- return nullptr;
- }
- void Sprite3DMaterial::setTexture(Texture2D* tex, NTextureData::Usage usage)
- {
- const auto& passes = getTechnique()->getPasses();
- for (auto& pass : passes) {
- pass->getGLProgramState()->setUniformTexture(s_uniformSamplerName[(int)usage], tex);
- }
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////////
- Sprite3DMaterialCache::Sprite3DMaterialCache()
- {
-
- }
- Sprite3DMaterialCache::~Sprite3DMaterialCache()
- {
- removeAllSprite3DMaterial();
- }
- Sprite3DMaterialCache* Sprite3DMaterialCache::getInstance()
- {
- if (! _cacheInstance)
- {
- _cacheInstance = new (std::nothrow) Sprite3DMaterialCache();
- }
-
- return _cacheInstance;
- }
- void Sprite3DMaterialCache::destroyInstance()
- {
- if (_cacheInstance)
- {
- CC_SAFE_DELETE(_cacheInstance);
- }
- }
- bool Sprite3DMaterialCache::addSprite3DMaterial(const std::string& key, Texture2D* texture)
- {
- auto itr = _materials.find(key);
- if (itr == _materials.end())
- {
- CC_SAFE_RETAIN(texture);
- _materials[key] = texture;
- return true;
- }
- return false;
- }
- Texture2D* Sprite3DMaterialCache::getSprite3DMaterial(const std::string& key)
- {
- auto itr = _materials.find(key);
- if (itr != _materials.end())
- {
- return itr->second;
- }
- return nullptr;
- }
- void Sprite3DMaterialCache::removeAllSprite3DMaterial()
- {
- for (auto& itr : _materials) {
- CC_SAFE_RELEASE_NULL(itr.second);
- }
- _materials.clear();
- }
- void Sprite3DMaterialCache::removeUnusedSprite3DMaterial()
- {
- for(auto it=_materials.cbegin(), itCend = _materials.cend(); it != itCend; /* nothing */) {
- auto value = it->second;
- if( value->getReferenceCount() == 1 ) {
- CCLOG("cocos2d: GLProgramStateCache: removing unused GLProgramState");
-
- value->release();
- it = _materials.erase(it);
- } else {
- ++it;
- }
- }
- }
- NS_CC_END
|