kick
|
00001 // 00002 // shader.cpp 00003 // KickCPP 00004 // 00005 // Created by morten on 8/25/13. 00006 // Copyright (c) 2013 Morten Nobel-Joergensen. All rights reserved. 00007 // 00008 00009 #include "kick/material/shader.h" 00010 #include "kick/material/material.h" 00011 #include "kick/core/Project.h" 00012 #include "kick/core/engine.h" 00013 #include "kick/core/time.h" 00014 #include "kick/math/misc.h" 00015 #include <sstream> 00016 #include <vector> 00017 #include <iostream> 00018 #include <array> 00019 #include <cassert> 00020 #include <regex> 00021 #include <cstring> 00022 #include <algorithm> 00023 #include <iterator> 00024 #include <sstream> 00025 #include "kick/core/cpp_ext.h" 00026 #include "kick/scene/transform.h" 00027 #include "kick/scene/light.h" 00028 #include "kick/core/debug.h" 00029 using namespace std; 00030 00031 namespace kick { 00032 00033 #define casetype(X) case static_cast<int>(X): \ 00034 enumValue = X; \ 00035 break; 00036 00037 00038 00039 bool toEnum(int value, ShaderType& enumValue){ 00040 switch (value) { 00041 casetype(ShaderType::VertexShader); 00042 casetype(ShaderType::FragmentShader); 00043 #ifndef GL_ES_VERSION_2_0 00044 casetype(ShaderType::GeometryShader); 00045 #endif 00046 default: 00047 return false; 00048 } 00049 return true; 00050 } 00051 00052 bool toEnum(int value, ShaderErrorType& enumValue){ 00053 switch (value) { 00054 casetype(ShaderErrorType::VertexShader); 00055 casetype(ShaderErrorType::FragmentShader); 00056 #ifndef GL_ES_VERSION_2_0 00057 casetype(ShaderErrorType::GeometryShader); 00058 #endif 00059 casetype(ShaderErrorType::Linker); 00060 casetype(ShaderErrorType::IncompleteShader); 00061 default: 00062 return false; 00063 } 00064 return true; 00065 } 00066 00067 bool toEnum(int value, BlendType& enumValue){ 00068 switch (value) { 00069 casetype(BlendType::Zero); 00070 casetype(BlendType::One); 00071 casetype(BlendType::SrcColor); 00072 casetype(BlendType::OneMinusSrcColor); 00073 casetype(BlendType::DstColor); 00074 casetype(BlendType::OneMinusDstColor); 00075 casetype(BlendType::SrcAlpha); 00076 casetype(BlendType::OneMinusSrcAlpha); 00077 casetype(BlendType::DstAlpha); 00078 casetype(BlendType::OneMinusDstAlpha); 00079 casetype(BlendType::ConstantColor); 00080 casetype(BlendType::OneMinusConstantColor); 00081 casetype(BlendType::ConstantAlpha); 00082 casetype(BlendType::OneMinusConstantAlpha); 00083 default: 00084 return false; 00085 } 00086 return true; 00087 } 00088 00089 bool toEnum(int value, FaceCullingType& enumValue){ 00090 switch (value) { 00091 casetype(FaceCullingType::Front); 00092 casetype(FaceCullingType::Back); 00093 casetype(FaceCullingType::FrontAndBack); 00094 casetype(FaceCullingType::None); 00095 default: 00096 return false; 00097 } 00098 return true; 00099 } 00100 00101 bool toEnum(int value, ZTestType& enumValue){ 00102 switch (value) { 00103 casetype(ZTestType::Never); 00104 casetype(ZTestType::Less); 00105 casetype(ZTestType::Equal); 00106 casetype(ZTestType::LEqual); 00107 casetype(ZTestType::Greater); 00108 casetype(ZTestType::NotEqual); 00109 casetype(ZTestType::GEqual); 00110 casetype(ZTestType::Always); 00111 default: 00112 return false; 00113 } 00114 return true; 00115 } 00116 00117 ShaderObj::ShaderObj(ShaderType type) 00118 :shader(glCreateShader((GLenum)type)) 00119 { 00120 assert(shader != 0); 00121 assert(shader != GL_INVALID_ENUM); 00122 } 00123 00124 ShaderObj::ShaderObj(ShaderObj&& other) 00125 :shader(other.shader){ 00126 other.shader = 0; 00127 } 00128 00129 ShaderObj& ShaderObj::operator=(ShaderObj&& other){ 00130 if (this != &other){ 00131 glDeleteShader(shader); 00132 shader = other.shader; 00133 other.shader = 0; 00134 } 00135 return *this; 00136 } 00137 00138 ShaderObj::~ShaderObj(){ 00139 if (shader>0){ 00140 glDeleteShader(shader); 00141 } 00142 } 00143 00144 void ShaderObj::detach(GLuint shaderProgram){ 00145 // warn http://stackoverflow.com/a/9117411/420250 00146 glDetachShader(shaderProgram, shader); 00147 } 00148 00149 Shader::Shader(Shader&& s) 00150 00151 { 00152 *this = move(s); 00153 } 00154 00155 Shader& Shader::operator=(Shader&& o){ 00156 swap(mShaderProgram, o.mShaderProgram); 00157 swap(shaderSources, o.shaderSources); 00158 swap(outputAttributeName, o.outputAttributeName); 00159 swap(mShaderAttributes, o.mShaderAttributes); 00160 swap(shaderUniforms, o.shaderUniforms); 00161 swap(mBlendDFactorAlpha, o.mBlendDFactorAlpha); 00162 swap(mBlendDFactorRGB, o.mBlendDFactorRGB); 00163 swap(mBlendSFactorAlpha, o.mBlendSFactorAlpha); 00164 swap(mBlendSFactorRGB, o.mBlendSFactorRGB); 00165 swap(mDepthBufferWrite, o.mDepthBufferWrite); 00166 swap(mFaceCulling, o.mFaceCulling); 00167 swap(mPolygonOffsetEnabled, o.mPolygonOffsetEnabled); 00168 swap(mPolygonOffsetFactorAndUnit, o.mPolygonOffsetFactorAndUnit); 00169 swap(mZTest, o.mZTest); 00170 return *this; 00171 } 00172 00173 Shader::Shader(string vertexShader, string fragmentShader, string geometryShader) 00174 : mShaderProgram(0) 00175 { 00176 setShaderSource(ShaderType::VertexShader, vertexShader); 00177 setShaderSource(ShaderType::FragmentShader, fragmentShader); 00178 #ifndef GL_ES_VERSION_2_0 00179 setShaderSource(ShaderType::GeometryShader, geometryShader); 00180 #endif 00181 if (vertexShader.length()>0 && fragmentShader.length()>0) { 00182 apply(); 00183 } 00184 } 00185 00186 Shader::~Shader(){ 00187 if (mShaderProgram != 0){ 00188 glDeleteProgram(mShaderProgram); 00189 } 00190 } 00191 00192 const UniformDescriptor* Shader::getShaderUniform(std::string name) const{ 00193 for (auto & desc : shaderUniforms) { 00194 if (desc.name == name){ 00195 return &desc; 00196 } 00197 } 00198 return nullptr; 00199 } 00200 00201 vector<AttributeDescriptor > getActiveShaderAttributes(GLuint programid){ 00202 vector<AttributeDescriptor > res; 00203 int numberOfActiveAttributes; 00204 glGetProgramiv(programid,GL_ACTIVE_ATTRIBUTES,&numberOfActiveAttributes); 00205 GLint bufSize; 00206 glGetProgramiv(programid, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &bufSize); 00207 vector<GLchar> buffer(bufSize); 00208 for (GLuint i=0;i<numberOfActiveAttributes;i++){ 00209 AttributeDescriptor att{i}; 00210 glGetActiveAttrib(programid, 00211 i, 00212 bufSize, 00213 nullptr, 00214 &att.size, 00215 &att.type, 00216 buffer.data()); 00217 att.name = buffer.data(); 00218 att.semantic = to_semantic(att.name); 00219 if (att.semantic == VertexAttributeSemantic::Unknown){ 00220 logWarning(string{"Invalid vertex attribute in shader source: "}+att.name); 00221 } 00222 res.push_back(att); 00223 } 00224 00225 return move(res); 00226 } 00227 00228 void Shader::translateToGLSLES(string& source, ShaderType type){ 00229 // replace textures 00230 if (type == ShaderType::VertexShader){ 00231 static regex regExpSearchShim3 { R"(\n\s*out\b)"}; 00232 source = regex_replace(source, regExpSearchShim3, "\nvarying"); 00233 static regex regExpSearchShim4 { R"(\n\s*in\b)"}; 00234 source = regex_replace(source, regExpSearchShim4, "\nattribute"); 00235 } else { 00236 static regex regExpSearchShim2 { R"(\bfragColor\b)"}; 00237 source = regex_replace(source, regExpSearchShim2, "gl_FragColor"); 00238 static regex regExpSearchShim3 { R"(\n\s*out\b)"}; 00239 source = regex_replace(source, regExpSearchShim3, "\n// out"); 00240 static regex regExpSearchShim4 { R"(\n\s*in\b)"}; 00241 source = regex_replace(source, regExpSearchShim4, "\nvarying"); 00242 } 00243 00244 static regex regExpSearchShim1 { R"(\s*uniform\s+sampler([\w]*)\s+([\w_]*)\s*;.*)"}; 00245 istringstream iss(source); 00246 map<string,string> textureType; 00247 smatch match; 00248 for (std::string line; std::getline(iss, line); ) 00249 { 00250 regex_search(line, match, regExpSearchShim1); 00251 if (match.size() > 0){ 00252 string samplerType = match[1].str(); 00253 string samplerName = match[2].str(); 00254 textureType[samplerName] = samplerType; 00255 00256 } 00257 } 00258 00259 for (auto val : textureType){ 00260 regex regExpSearchShim4 { string{"texture\\s*\\(\\s*"}+val.first+"\\s*," }; 00261 source = regex_replace(source, regExpSearchShim4, string{"texture"}+val.second+"("+val.first+","); 00262 } 00263 } 00264 00265 vector<UniformDescriptor > getActiveShaderUniforms(GLuint programid){ 00266 vector<UniformDescriptor > res; 00267 00268 int numberOfActiveUniforms; 00269 glGetProgramiv(programid,GL_ACTIVE_UNIFORMS,&numberOfActiveUniforms); 00270 GLint bufSize; 00271 glGetProgramiv(programid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &bufSize); 00272 vector<GLchar> buffer(bufSize); 00273 for (GLuint i=0;i<numberOfActiveUniforms;i++){ 00274 UniformDescriptor uni{i}; 00275 glGetActiveUniform(programid, 00276 i, 00277 bufSize, 00278 nullptr, 00279 &uni.size, 00280 &uni.type, 00281 buffer.data()); 00282 uni.name = buffer.data(); 00283 int index = glGetUniformLocation(programid, buffer.data()); 00284 if (index>=0){ 00285 uni.index = index; 00286 res.push_back(uni); 00287 } else { 00288 cout << "cannot find uniform index "<< buffer.data()<<endl; 00289 } 00290 } 00291 00292 return move(res); 00293 } 00294 00295 string Shader::getPrecompiledSource(string source, ShaderType type) { 00296 if (source.find("#version") != 0){ 00297 #ifdef GL_ES_VERSION_2_0 00298 string prefix = "#version 100\n";// context.getGLSLPrefix() // todo - get prefix from context 00299 #else 00300 string prefix = "#version 150\n";// context.getGLSLPrefix() // todo - get prefix from context 00301 #endif 00302 source = prefix + source; 00303 } 00304 string precisionSpecifier = ""; 00305 00306 00307 // remove commented out usages of #pragma include 00308 static regex regExpSearch { R"(//\s*#?\s*pragma\s+include[^\n]*)"}; 00309 source = regex_replace(source, regExpSearch, ""); 00310 00311 // find pragma include files 00312 static regex regExpSearch2 { "[ ]*#\\s*pragma\\s+include\\s+\"([^\"]*)\"[^\\n]*"}; 00313 vector<string> includeNames; 00314 auto iter = std::sregex_token_iterator(source.begin(), source.end(), regExpSearch2, 1); 00315 auto endIter = std::sregex_token_iterator(); 00316 while (iter != endIter){ 00317 includeNames.push_back(*iter); 00318 iter++; 00319 } 00320 00321 // replace source 00322 for (auto includeName : includeNames){ 00323 string includedSource; 00324 if (Project::loadTextResource(includeName, includedSource)) { 00325 if (includedSource.size() == 0) { 00326 cout << "Could not load source " << includeName << endl; 00327 } else { 00328 regex regExpSearch3{string{"[ ]*#\\s*pragma\\s+include\\s+\""} + includeName + "\"[^\\n]*"}; 00329 source = regex_replace(source, regExpSearch3, includedSource); 00330 } 00331 } 00332 } 00333 00334 #ifdef GL_ES_VERSION_2_0 00335 translateToGLSLES(source, type); 00336 if (type == ShaderType::FragmentShader){ 00337 precisionSpecifier = "precision mediump float;\n"; 00338 } 00339 #endif 00340 // Insert compile 00341 size_t indexOfNewline = source.find('\n'); 00342 string version = source.substr(0, indexOfNewline); // save version info 00343 source = source.substr(indexOfNewline + 1); // strip version info 00344 00345 00346 source = version + "\n" + 00347 precisionSpecifier+ 00348 "#define SHADOWS " + (Engine::config().shadows?"true":"false") + "\n" + 00349 "#define LIGHTS " + std::to_string((int) Engine::config().maxNumerOfLights) + "\n" + 00350 "#line " + std::to_string(2) + "\n" + 00351 source; 00352 00353 return source; 00354 } 00355 00356 bool Shader::apply(){ 00357 if (mShaderProgram){ 00358 glDeleteShader(mShaderProgram); 00359 } 00360 mShaderProgram = glCreateProgram(); 00361 vector<ShaderObj> shaderObjects; 00362 vector<ShaderType> requiredTypes{ShaderType::VertexShader, ShaderType::FragmentShader}; 00363 for (auto & element : shaderSources) { 00364 auto shaderType = element.first; 00365 string & source = element.second; 00366 if (source.length()>0){ 00367 string precompiledSource = getPrecompiledSource(source, shaderType); 00368 00369 shaderObjects.push_back(compileShader(precompiledSource, shaderType)); 00370 // remove element from vector 00371 requiredTypes.erase(std::remove(requiredTypes.begin(), requiredTypes.end(), shaderType), requiredTypes.end()); 00372 glAttachShader(mShaderProgram, shaderObjects.back()); 00373 } 00374 } 00375 if (requiredTypes.size()>0){ 00376 logError("Both vertex and fragment shader required."); 00377 return false; 00378 } 00379 00380 bool linked = linkProgram(); 00381 if (!linked){ 00382 return false; 00383 } 00384 // shaderObjects deleted when goes out of scope (which is ok as long as program is not deleted) 00385 glUseProgram(mShaderProgram); 00386 00387 mShaderAttributes = getActiveShaderAttributes(mShaderProgram); 00388 shaderUniforms = getActiveShaderUniforms(mShaderProgram); 00389 00390 updateDefaultShaderLocation(); 00391 00392 shaderChanged.notifyListeners({this, ShaderEventType::shader }); 00393 00394 // clean up 00395 for (auto & shaderObject : shaderObjects){ 00396 shaderObject.detach(mShaderProgram); 00397 } 00398 shaderObjects.clear(); 00399 00400 return true; 00401 } 00402 00403 bool Shader::linkProgram(){ 00404 #ifndef GL_ES_VERSION_2_0 00405 glBindFragDataLocation(mShaderProgram, 0, outputAttributeName.c_str()); 00406 #endif 00407 glLinkProgram(mShaderProgram); 00408 00409 GLint linked; 00410 glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &linked ); 00411 if (linked == GL_FALSE) { 00412 GLint logSize; 00413 glGetProgramiv(mShaderProgram, GL_INFO_LOG_LENGTH, &logSize); 00414 vector<char> errorLog((size_t) logSize); 00415 glGetProgramInfoLog(mShaderProgram, logSize, NULL, errorLog.data() ); 00416 // throw ShaderBuildException{, ShaderErrorType::Linker}; 00417 logError(errorLog.data()); 00418 return false; 00419 } 00420 return true; 00421 } 00422 00423 void updateFaceCulling(FaceCullingType faceCulling){ 00424 if (faceCulling == FaceCullingType::None){ 00425 glDisable(GL_CULL_FACE); 00426 } else { 00427 glEnable(GL_CULL_FACE); 00428 glCullFace(static_cast<GLuint>(faceCulling)); 00429 } 00430 } 00431 00432 void updateDepthProperties(ZTestType zTest, bool depthWrite){ 00433 if (zTest == ZTestType::Never){ 00434 glDisable(GL_DEPTH_TEST); 00435 } else { 00436 glEnable(GL_DEPTH_TEST); 00437 } 00438 glDepthFunc(static_cast<GLuint>(zTest)); 00439 glDepthMask(depthWrite ? GL_TRUE : GL_FALSE); 00440 } 00441 00442 void updateBlending(bool blend, BlendType blendDFactorAlpha,BlendType blendDFactorRGB, BlendType blendSFactorAlpha, BlendType blendSFactorRGB){ 00443 if (blend){ 00444 glEnable(GL_BLEND); 00445 GLenum sfactorRGB = static_cast<GLenum>(blendSFactorRGB); 00446 GLenum dfactorRGB = static_cast<GLenum>(blendDFactorRGB); 00447 GLenum sfactorAlpha = static_cast<GLenum>(blendSFactorAlpha); 00448 GLenum dfactorAlpha = static_cast<GLenum>(blendDFactorAlpha);; 00449 glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); 00450 } else { 00451 glDisable(GL_BLEND); 00452 } 00453 } 00454 00455 void Shader::bind(){ 00456 glUseProgram(mShaderProgram); 00457 updateFaceCulling(mFaceCulling); 00458 updateDepthProperties(mZTest, mDepthBufferWrite); 00459 updateBlending(mBlend, mBlendDFactorAlpha, mBlendDFactorRGB, mBlendSFactorAlpha, mBlendSFactorRGB); 00460 } 00461 00462 ShaderObj Shader::compileShader(std::string source, ShaderType type){ 00463 ShaderObj shader(type); 00464 const GLchar* sourceArray[1]; 00465 sourceArray[0] = source.c_str(); 00466 GLint stringLengths[1]; 00467 stringLengths[0] = (GLint)source.length(); 00468 glShaderSource(shader, 1, sourceArray, stringLengths); 00469 glCompileShader(shader); 00470 GLint success = 0; 00471 glGetShaderiv(shader, GL_COMPILE_STATUS, &success); 00472 if (success == GL_FALSE){ 00473 ShaderBuildException::logCurrentCompileException(shader, (ShaderErrorType) type, source); 00474 } 00475 return move(shader); 00476 } 00477 00478 void Shader::setShaderSource(ShaderType type, string str){ 00479 shaderSources[type] = str; 00480 } 00481 00482 std::string Shader::getShaderSource(ShaderType type) const { 00483 return shaderSources.at(type); 00484 } 00485 00486 std::string Shader::getPrecompiledShaderSource(ShaderType type) const{ 00487 string value = getShaderSource(type); 00488 return getPrecompiledSource(value, type); 00489 } 00490 00491 const std::vector<AttributeDescriptor >& Shader::getShaderAttributes() const { 00492 return mShaderAttributes; 00493 } 00494 00495 const std::vector<UniformDescriptor >& Shader::getShaderUniforms() const { 00496 return shaderUniforms; 00497 } 00498 00499 const AttributeDescriptor* Shader::getShaderAttribute(VertexAttributeSemantic semantic) const{ 00500 for (int i=0;i< mShaderAttributes.size();i++){ 00501 if (mShaderAttributes[i].semantic == semantic){ 00502 return &mShaderAttributes[i]; 00503 } 00504 } 00505 return nullptr; 00506 } 00507 00508 string ShaderBuildException::extractLines(std::string errorMessage, std::string source, int extraLines){ 00509 static regex regExpSearch { R"(\d+:(\d+))"}; 00510 auto iter = std::sregex_token_iterator(errorMessage.begin(), errorMessage.end(), regExpSearch, 1); 00511 auto endIter = std::sregex_token_iterator(); 00512 if (iter != endIter){ 00513 string lineStr = *iter; 00514 int line = atoi(lineStr.c_str()); 00515 const int buffer_size = 512; 00516 array<char, buffer_size> lineBuffer; 00517 istringstream inbuf(source); 00518 string res; 00519 for (int i=1;i<=line+extraLines && inbuf.getline(lineBuffer.data(),buffer_size);i++){ 00520 if (strncmp(lineBuffer.data(), "#line ", 6)==0){ 00521 string s{lineBuffer.data()}; 00522 static regex regExpSearchLine { R"((\d+))"}; 00523 auto iterLine = std::sregex_token_iterator(s.begin(), s.end(), regExpSearchLine, 1); 00524 if (iterLine != endIter){ 00525 string newLineNumberStr = *iterLine; 00526 i = atoi(newLineNumberStr.c_str()); 00527 } 00528 } 00529 if (i >= line-extraLines){ 00530 res += std::to_string(i)+"\t"+string{lineBuffer.data()}+"\n"; 00531 } 00532 } 00533 return res; 00534 } else 00535 return ""; 00536 } 00537 00538 00539 void ShaderBuildException::logCurrentCompileException(GLuint shader, ShaderErrorType type, string source){ 00540 GLint logSize = 0; 00541 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize); 00542 00543 vector<char> errorLog((unsigned long) logSize); 00544 glGetShaderInfoLog(shader, logSize, &logSize, errorLog.data()); 00545 string errorLines = extractLines(errorLog.data(), source); 00546 string typeStr; 00547 switch (type){ 00548 case ShaderErrorType::FragmentShader: 00549 typeStr = "Fragment shader"; 00550 break; 00551 #ifndef GL_ES_VERSION_2_0 00552 case ShaderErrorType::GeometryShader: 00553 typeStr = "Geometry shader"; 00554 break; 00555 #endif 00556 case ShaderErrorType::IncompleteShader: 00557 typeStr = "Incomplete shader"; 00558 break; 00559 case ShaderErrorType::Linker: 00560 typeStr = "Linker"; 00561 break; 00562 case ShaderErrorType::VertexShader : 00563 typeStr = "Vertex shader"; 00564 break; 00565 00566 } 00567 logError(string{errorLog.data()}+"\n"+ typeStr +" error\n"+ errorLines); 00568 } 00569 00570 void Shader::setBlend(bool b){ mBlend = b; } 00571 bool Shader::blend() { return mBlend; } 00572 BlendType Shader::blendDFactorAlpha() { return mBlendDFactorAlpha; } 00573 BlendType Shader::blendDFactorRGB() { return mBlendDFactorRGB; } 00574 BlendType Shader::blendSFactorAlpha() { return mBlendSFactorAlpha; } 00575 BlendType Shader::blendSFactorRGB() { return mBlendSFactorRGB; } 00576 void Shader::setBlendDFactorAlpha(BlendType blendDFactorAlpha) { this->mBlendDFactorAlpha =blendDFactorAlpha; } 00577 void Shader::setBlendDFactorRGB(BlendType blendDFactorRGB) { this->mBlendDFactorRGB =blendDFactorRGB; } 00578 void Shader::setBlendSFactorAlpha(BlendType blendSFactorAlpha) { this->mBlendSFactorAlpha = blendSFactorAlpha; } 00579 void Shader::setBlendSFactorRGB(BlendType blendSFactorRGB) { this->mBlendSFactorRGB = blendSFactorRGB; } 00580 void Shader::setDepthWrite(bool depthMask) { this->mDepthBufferWrite = depthMask;} 00581 bool Shader::depthWrite() { return mDepthBufferWrite; } 00582 void Shader::setFaceCulling(FaceCullingType faceCulling) { this->mFaceCulling = faceCulling; } 00583 FaceCullingType Shader::faceCulling() { return mFaceCulling; } 00584 void Shader::setPolygonOffsetEnabled(bool polygonOffsetEnabled) { this->mPolygonOffsetEnabled = polygonOffsetEnabled; } 00585 bool Shader::polygonOffsetEnabled() { return mPolygonOffsetEnabled; } 00586 void Shader::setPolygonOffsetFactorAndUnit(glm::vec2 polygonOffsetFactorAndUnit) { this->mPolygonOffsetFactorAndUnit = polygonOffsetFactorAndUnit; } 00587 glm::vec2 Shader::polygonOffsetFactorAndUnit() { return mPolygonOffsetFactorAndUnit; } 00588 void Shader::setZTest(ZTestType zTest) { this->mZTest = zTest; } 00589 ZTestType Shader::zTest() { return mZTest; } 00590 00591 void Shader::bind_uniforms(Material *material, EngineUniforms *engineUniforms, Transform* transform){ 00592 material->bind(); 00593 SceneLights * sceneLights = engineUniforms->sceneLights; 00594 for (auto& uniform : shaderUniforms){ 00595 if (uniform.name == UniformNames::modelMatrix){ 00596 auto globalMatrix = transform->globalMatrix(); 00597 glUniformMatrix4fv(uniform.index, 1, GL_FALSE, glm::value_ptr(globalMatrix)); 00598 } else if (uniform.name == UniformNames::mv){ 00599 auto modelView = engineUniforms->viewMatrix * transform->globalMatrix(); 00600 glUniformMatrix4fv(uniform.index, 1, GL_FALSE, glm::value_ptr(modelView)); 00601 } else if (uniform.name == UniformNames::norm) { 00602 auto modelView = engineUniforms->viewMatrix * transform->globalMatrix(); 00603 auto normal = glm::inverseTranspose(glm::mat3(modelView)); 00604 glUniformMatrix3fv(uniform.index, 1, GL_FALSE, glm::value_ptr(normal)); 00605 } else if (uniform.name == UniformNames::v) { 00606 auto viewMatrix = engineUniforms->viewMatrix; 00607 glUniformMatrix4fv(uniform.index, 1, GL_FALSE, glm::value_ptr(viewMatrix)); 00608 } else if (uniform.name == UniformNames::proj){ 00609 glUniformMatrix4fv(uniform.index, 1, GL_FALSE, glm::value_ptr(engineUniforms->projectionMatrix)); 00610 } else if (uniform.name == UniformNames::worldCamPos){ 00611 auto cameraPos = engineUniforms->currentCameraTransform->position(); 00612 glUniform3fv(uniform.index, 1, glm::value_ptr(cameraPos)); 00613 } else if (uniform.name == UniformNames::world2object){ 00614 auto world2object = transform->globalTRSInverse(); 00615 glUniformMatrix4fv(uniform.index, 1, GL_FALSE, glm::value_ptr(world2object)); 00616 } else if (uniform.name == UniformNames::mvProj){ 00617 auto mvProj = engineUniforms->viewProjectionMatrix * transform->globalMatrix(); 00618 glUniformMatrix4fv(uniform.index, 1, GL_FALSE, glm::value_ptr(mvProj)); 00619 } else if (uniform.name == UniformNames::gameObjectUID){ 00620 int32_t uid = transform->gameObject()->uniqueId(); 00621 glm::vec4 packedInt = uint32ToVec4(uid); 00622 glUniform4fv(uniform.index, 1, glm::value_ptr(packedInt )); 00623 } else if (uniform.name == UniformNames::shadowMapTexture) { 00624 //throw invalid_argument("shadowMapTexture not yet implemented"); // todo 00625 cout <<"shadowMapTexture not yet implemented\n"; // todo 00626 logWarning("\"shadowMapTexture not yet implemented"); 00627 } else if (uniform.name == UniformNames::lightMat){ 00628 auto lightMatrix = engineUniforms->lightMatrix * transform->globalMatrix(); 00629 glUniformMatrix4fv(uniform.index, 1, GL_FALSE, glm::value_ptr(lightMatrix)); 00630 } else if (uniform.name == UniformNames::ambient){ 00631 glm::vec3 ambientLight = sceneLights->ambientLight ? sceneLights->ambientLight->colorIntensity() : glm::vec3{0}; 00632 glUniform3fv(uniform.index, 1, glm::value_ptr(ambientLight)); 00633 } else if (uniform.name == UniformNames::pointLight){ 00634 glUniformMatrix3fv(uniform.index, KICK_MAX_POINT_LIGHTS, GL_FALSE, glm::value_ptr(sceneLights->pointLightData[0])); 00635 } else if (uniform.name == UniformNames::directionalLight){ 00636 glUniformMatrix3fv(uniform.index, 1, GL_FALSE, glm::value_ptr(sceneLights->directionalLightData)); 00637 } else if (uniform.name == UniformNames::directionalLightWorld){ 00638 glUniform3fv(uniform.index, 1, glm::value_ptr(sceneLights->directionalLightWorld)); 00639 } else if (uniform.name == UniformNames::time){ 00640 float time = Time::total(); 00641 glUniform1f(uniform.index, time); 00642 } else if (uniform.name == UniformNames::viewport){ 00643 glm::vec2 viewportSize = (glm::vec2)engineUniforms->viewportDimension.getValue(); 00644 glUniform2fv(uniform.index, 1, glm::value_ptr(viewportSize)); 00645 } 00646 00647 // debug output 00648 //else { 00649 // continue; 00650 //} 00651 //cout << to_string(uniform)<<"\n"; 00652 } 00653 } 00654 00655 void Shader::updateDefaultShaderLocation(){ 00656 for (auto & e : defaultUniformData){ 00657 updateShaderLocation(e.first, e.second); 00658 } 00659 } 00660 00661 void Shader::updateShaderLocation(std::string name, MaterialData& value){ 00662 auto descriptor = getShaderUniform(name); 00663 value.defaultUniform = true; 00664 if (descriptor == nullptr){ 00665 value.shaderLocation = -1; 00666 } else { 00667 value.shaderLocation = descriptor->index; 00668 } 00669 } 00670 00671 void Shader::setDefaultUniformData(std::string name, MaterialData &&value) { 00672 auto pos = defaultUniformData.find(name); 00673 if (pos != defaultUniformData.end()){ 00674 pos->second.setValue(value.value); 00675 if (pos->second.glType != value.glType){ 00676 pos->second.glType = value.glType; 00677 updateShaderLocation(name, pos->second); 00678 } 00679 } else { 00680 // not found insert new 00681 auto insertedElement = defaultUniformData.emplace(make_pair(name, move(value))); 00682 bool didInsert = insertedElement.second; 00683 assert(didInsert); 00684 auto insertedIterator = insertedElement.first; 00685 updateShaderLocation(name, insertedIterator->second); 00686 } 00687 shaderChanged.notifyListeners({this, ShaderEventType::defaultUniform }); 00688 } 00689 00690 bool Shader::tryGetDefaultUniform(std::string name, MaterialData &value) { 00691 auto pos = defaultUniformData.find(name); 00692 if (pos != defaultUniformData.end()){ 00693 value = pos->second; 00694 return true; 00695 } 00696 return false; 00697 } 00698 00699 int Shader::getRenderOrder() const { 00700 return mDenderOrder; 00701 } 00702 00703 void Shader::setRenderOrder(int renderOrder) { 00704 if (renderOrder != Shader::mDenderOrder){ 00705 Shader::mDenderOrder = renderOrder; 00706 shaderChanged.notifyListeners({this, ShaderEventType::shader }); 00707 } 00708 } 00709 00710 void Shader::setDefaultUniform(std::string name, int value) { setDefaultUniformInternal(name, value); } 00711 00712 void Shader::setDefaultUniform(std::string name, float value) { setDefaultUniformInternal(name, value); } 00713 00714 void Shader::setDefaultUniform(std::string name, glm::vec4 value) { setDefaultUniformInternal(name, value); } 00715 00716 void Shader::setDefaultUniform(std::string name, glm::mat3 value) { setDefaultUniformInternal(name, value); } 00717 00718 void Shader::setDefaultUniform(std::string name, glm::mat4 value) { setDefaultUniformInternal(name, value); } 00719 00720 void Shader::setDefaultUniform(std::string name, std::shared_ptr<Texture2D> value) { 00721 texture2DRef[name] = value; 00722 setDefaultUniformInternal(name, value.get()); 00723 } 00724 00725 void Shader::setDefaultUniform(std::string name, std::shared_ptr<TextureCube> value) { 00726 textureCubeRef[name] = value; 00727 setDefaultUniformInternal(name, value.get()); 00728 } 00729 }