123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- #include "renderer/CCMaterial.h"
- #include "renderer/CCTechnique.h"
- #include "renderer/CCPass.h"
- #include "renderer/CCTextureCache.h"
- #include "renderer/CCTexture2D.h"
- #include "renderer/CCGLProgram.h"
- #include "renderer/CCGLProgramState.h"
- #include "base/CCProperties.h"
- #include "base/CCDirector.h"
- #include "platform/CCFileUtils.h"
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
- #define strcasecmp _stricmp
- #endif
- NS_CC_BEGIN
- static const char* getOptionalString(Properties* properties, const char* key, const char* defaultValue);
- static bool isValidUniform(const char* name);
- Material* Material::createWithFilename(const std::string& filepath)
- {
- auto validfilename = FileUtils::getInstance()->fullPathForFilename(filepath);
- if (validfilename.size() > 0) {
- auto mat = new (std::nothrow) Material();
- if (mat && mat->initWithFile(validfilename))
- {
- mat->autorelease();
- return mat;
- }
- }
- return nullptr;
- }
- Material* Material::createWithProperties(Properties* materialProperties)
- {
- auto mat = new (std::nothrow) Material();
- if (mat && mat->initWithProperties(materialProperties))
- {
- mat->autorelease();
- return mat;
- }
- return nullptr;
- }
- Material* Material::createWithGLStateProgram(GLProgramState* programState)
- {
- CCASSERT(programState, "Invalid GL Program State");
- auto mat = new (std::nothrow) Material();
- if (mat && mat->initWithGLProgramState(programState))
- {
- mat->autorelease();
- return mat;
- }
- return nullptr;
- }
- bool Material::initWithGLProgramState(cocos2d::GLProgramState *state)
- {
- auto technique = Technique::createWithGLProgramState(this, state);
- if (technique) {
- _techniques.pushBack(technique);
-
- _currentTechnique = technique;
- return true;
- }
- return false;
- }
- bool Material::initWithFile(const std::string& validfilename)
- {
-
- Properties* properties = Properties::createNonRefCounted(validfilename);
-
- parseProperties((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
- CC_SAFE_DELETE(properties);
- return true;
- }
- bool Material::initWithProperties(Properties* materialProperties)
- {
- return parseProperties(materialProperties);
- }
- void Material::setTarget(cocos2d::Node *target)
- {
- _target = target;
- }
- bool Material::parseProperties(Properties* materialProperties)
- {
- setName(materialProperties->getId());
- auto space = materialProperties->getNextNamespace();
- while (space)
- {
- const char* name = space->getNamespace();
- if (strcmp(name, "technique") == 0)
- {
- parseTechnique(space);
- }
- else if (strcmp(name, "renderState") == 0)
- {
- parseRenderState(this, space);
- }
- space = materialProperties->getNextNamespace();
- }
- return true;
- }
- bool Material::parseTechnique(Properties* techniqueProperties)
- {
- auto technique = Technique::create(this);
- _techniques.pushBack(technique);
-
- if (!_currentTechnique)
- _currentTechnique = technique;
-
- technique->setName(techniqueProperties->getId());
-
- auto space = techniqueProperties->getNextNamespace();
- while (space)
- {
- const char* name = space->getNamespace();
- if (strcmp(name, "pass") == 0)
- {
- parsePass(technique, space);
- }
- else if (strcmp(name, "renderState") == 0)
- {
- parseRenderState(this, space);
- }
- space = techniqueProperties->getNextNamespace();
- }
- return true;
- }
- bool Material::parsePass(Technique* technique, Properties* passProperties)
- {
- auto pass = Pass::create(technique);
- technique->addPass(pass);
-
-
-
-
- auto space = passProperties->getNextNamespace();
- while (space)
- {
- const char* name = space->getNamespace();
- if (strcmp(name, "shader") == 0)
- parseShader(pass, space);
- else if (strcmp(name, "renderState") == 0)
- parseRenderState(pass, space);
- else {
- CCASSERT(false, "Invalid namespace");
- return false;
- }
- space = passProperties->getNextNamespace();
- }
- return true;
- }
- bool Material::parseSampler(GLProgramState* glProgramState, Properties* samplerProperties)
- {
- CCASSERT(samplerProperties->getId(), "Sampler must have an id. The id is the uniform name");
-
-
- auto filename = samplerProperties->getString("path");
- auto texture = Director::getInstance()->getTextureCache()->addImage(filename);
- if (!texture) {
- CCLOG("Invalid filepath");
- return false;
- }
-
- {
- Texture2D::TexParams texParams;
-
- bool usemipmap = false;
- const char* mipmap = getOptionalString(samplerProperties, "mipmap", "false");
- if (mipmap && strcasecmp(mipmap, "true")==0) {
- texture->generateMipmap();
- usemipmap = true;
- }
-
- const char* wrapS = getOptionalString(samplerProperties, "wrapS", "CLAMP_TO_EDGE");
- if (strcasecmp(wrapS, "REPEAT")==0)
- texParams.wrapS = GL_REPEAT;
- else if(strcasecmp(wrapS, "CLAMP_TO_EDGE")==0)
- texParams.wrapS = GL_CLAMP_TO_EDGE;
- else
- CCLOG("Invalid wrapS: %s", wrapS);
-
- const char* wrapT = getOptionalString(samplerProperties, "wrapT", "CLAMP_TO_EDGE");
- if (strcasecmp(wrapT, "REPEAT")==0)
- texParams.wrapT = GL_REPEAT;
- else if(strcasecmp(wrapT, "CLAMP_TO_EDGE")==0)
- texParams.wrapT = GL_CLAMP_TO_EDGE;
- else
- CCLOG("Invalid wrapT: %s", wrapT);
-
- const char* minFilter = getOptionalString(samplerProperties, "minFilter", usemipmap ? "LINEAR_MIPMAP_NEAREST" : "LINEAR");
- if (strcasecmp(minFilter, "NEAREST")==0)
- texParams.minFilter = GL_NEAREST;
- else if(strcasecmp(minFilter, "LINEAR")==0)
- texParams.minFilter = GL_LINEAR;
- else if(strcasecmp(minFilter, "NEAREST_MIPMAP_NEAREST")==0)
- texParams.minFilter = GL_NEAREST_MIPMAP_NEAREST;
- else if(strcasecmp(minFilter, "LINEAR_MIPMAP_NEAREST")==0)
- texParams.minFilter = GL_LINEAR_MIPMAP_NEAREST;
- else if(strcasecmp(minFilter, "NEAREST_MIPMAP_LINEAR")==0)
- texParams.minFilter = GL_NEAREST_MIPMAP_LINEAR;
- else if(strcasecmp(minFilter, "LINEAR_MIPMAP_LINEAR")==0)
- texParams.minFilter = GL_LINEAR_MIPMAP_LINEAR;
- else
- CCLOG("Invalid minFilter: %s", minFilter);
-
- const char* magFilter = getOptionalString(samplerProperties, "magFilter", "LINEAR");
- if (strcasecmp(magFilter, "NEAREST")==0)
- texParams.magFilter = GL_NEAREST;
- else if(strcasecmp(magFilter, "LINEAR")==0)
- texParams.magFilter = GL_LINEAR;
- else
- CCLOG("Invalid magFilter: %s", magFilter);
- texture->setTexParameters(texParams);
- }
- glProgramState->setUniformTexture(samplerProperties->getId(), texture);
- return true;
- }
- bool Material::parseShader(Pass* pass, Properties* shaderProperties)
- {
-
- const char* vertShader = getOptionalString(shaderProperties, "vertexShader", nullptr);
-
- const char* fragShader = getOptionalString(shaderProperties, "fragmentShader", nullptr);
-
- const char* compileTimeDefines = getOptionalString(shaderProperties, "defines", "");
- if (vertShader && fragShader)
- {
- auto glProgramState = GLProgramState::getOrCreateWithShaders(vertShader, fragShader, compileTimeDefines);
- pass->setGLProgramState(glProgramState);
-
- auto property = shaderProperties->getNextProperty();
- while (property)
- {
- if (isValidUniform(property))
- {
- parseUniform(glProgramState, shaderProperties, property);
- }
- property = shaderProperties->getNextProperty();
- }
- auto space = shaderProperties->getNextNamespace();
- while (space)
- {
- const char* name = space->getNamespace();
- if (strcmp(name, "sampler") == 0)
- {
- parseSampler(glProgramState, space);
- }
- space = shaderProperties->getNextNamespace();
- }
- }
- return true;
- }
- bool Material::parseUniform(GLProgramState* programState, Properties* properties, const char* uniformName)
- {
- bool ret = true;
- auto type = properties->getType(uniformName);
- switch (type) {
- case Properties::Type::NUMBER:
- {
- auto f = properties->getFloat(uniformName);
- programState->setUniformFloat(uniformName, f);
- break;
- }
- case Properties::Type::VECTOR2:
- {
- Vec2 v2;
- properties->getVec2(uniformName, &v2);
- programState->setUniformVec2(uniformName, v2);
- break;
- }
- case Properties::Type::VECTOR3:
- {
- Vec3 v3;
- properties->getVec3(uniformName, &v3);
- programState->setUniformVec3(uniformName, v3);
- break;
- }
- case Properties::Type::VECTOR4:
- {
- Vec4 v4;
- properties->getVec4(uniformName, &v4);
- programState->setUniformVec4(uniformName, v4);
- break;
- }
- case Properties::Type::MATRIX:
- {
- Mat4 m4;
- properties->getMat4(uniformName, &m4);
- programState->setUniformMat4(uniformName, m4);
- break;
- }
- case Properties::Type::STRING:
- default:
- {
-
- programState->setParameterAutoBinding(uniformName, properties->getString());
- break;
- }
- }
- return ret;
- }
- bool Material::parseRenderState(RenderState* renderState, Properties* properties)
- {
- auto state = renderState->getStateBlock();
- auto property = properties->getNextProperty();
- while (property)
- {
-
-
- state->setState(property, properties->getString(property));
- property = properties->getNextProperty();
- }
- return true;
- }
- void Material::setName(const std::string&name)
- {
- _name = name;
- }
- std::string Material::getName() const
- {
- return _name;
- }
- Material::Material()
- : _name("")
- , _currentTechnique(nullptr)
- , _target(nullptr)
- {
- }
- Material::~Material()
- {
- }
- Material* Material::clone() const
- {
- auto material = new (std::nothrow) Material();
- if (material)
- {
- RenderState::cloneInto(material);
- for (const auto& technique: _techniques)
- {
- auto t = technique->clone();
- t->_parent = material;
- material->_techniques.pushBack(t);
- }
-
- auto name = _currentTechnique->getName();
- material->_currentTechnique = material->getTechniqueByName(name);
- material->autorelease();
- }
- return material;
- }
- Technique* Material::getTechnique() const
- {
- return _currentTechnique;
- }
- const Vector<Technique*>& Material::getTechniques() const
- {
- return _techniques;
- }
- Technique* Material::getTechniqueByName(const std::string& name)
- {
- for(const auto& technique : _techniques) {
- if (technique->getName().compare(name)==0)
- return technique;
- }
- return nullptr;
- }
- Technique* Material::getTechniqueByIndex(ssize_t index)
- {
- CC_ASSERT(index>=0 && index<_techniques.size() && "Invalid size");
- return _techniques.at(index);
- }
- void Material::addTechnique(Technique* technique)
- {
- _techniques.pushBack(technique);
- }
- void Material::setTechnique(const std::string& techniqueName)
- {
- auto technique = getTechniqueByName(techniqueName);
- if (technique)
- _currentTechnique = technique;
- }
- ssize_t Material::getTechniqueCount() const
- {
- return _techniques.size();
- }
- static bool isValidUniform(const char* name)
- {
- return !(strcmp(name, "defines")==0 ||
- strcmp(name, "vertexShader")==0 ||
- strcmp(name, "fragmentShader")==0);
- }
- static const char* getOptionalString(Properties* properties, const char* key, const char* defaultValue)
- {
- const char* ret = properties->getString(key);
- if (!ret)
- ret = defaultValue;
- return ret;
- }
- NS_CC_END
|