#include "ShaderManager.h" #include namespace ZL { ShaderResource::ShaderResource(const std::string& vertexCode, const std::string& fragmentCode) { const int CONST_INFOLOG_LENGTH = 256; char infoLog[CONST_INFOLOG_LENGTH]; int infoLogLength; int vertexShaderCompiled; int fragmentShaderCompiled; int programLinked; GLuint vertexShader; GLuint fragmentShader; int vertexCodeLength = static_cast(strlen(vertexCode.c_str())); int fragmentCodeLength = static_cast(strlen(fragmentCode.c_str())); const char* vc = &vertexCode[0]; const char* fc = &fragmentCode[0]; vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &(vc), &vertexCodeLength); fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &(fc), &fragmentCodeLength); glCompileShader(vertexShader); glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexShaderCompiled); glGetShaderInfoLog(vertexShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog); glCompileShader(fragmentShader); glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentShaderCompiled); glGetShaderInfoLog(fragmentShader, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog); if (!vertexShaderCompiled) { throw std::runtime_error("Failed to compile vertex shader code!"); } std::cout << "IM here" << std::endl; if (!fragmentShaderCompiled) { throw std::runtime_error("Failed to compile fragment shader code!"); } shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); glDeleteShader(vertexShader); glDeleteShader(fragmentShader); glGetProgramiv(shaderProgram, GL_LINK_STATUS, &programLinked); glGetProgramInfoLog(shaderProgram, CONST_INFOLOG_LENGTH, &infoLogLength, infoLog); if (!programLinked) { shaderProgram = 0; throw std::runtime_error("Failed to link shader program!"); } int dummySize; //Dummy int dummyLen; //Dummy GLenum dummyEnum; //================= Parsing all uniforms ================ int activeUniforms; const int CONST_UNIFORM_NAME_LENGTH = 256; char uniformName[CONST_UNIFORM_NAME_LENGTH]; glGetProgramiv(shaderProgram, GL_ACTIVE_UNIFORMS, &activeUniforms); for (int i = 0; i < activeUniforms; i++) { glGetActiveUniform(shaderProgram, i, CONST_UNIFORM_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, uniformName); uniformList[uniformName] = glGetUniformLocation(shaderProgram, uniformName); } //================= Parsing all attributes ================ int activeAttribs; const int CONST_ATTRIB_NAME_LENGTH = 256; char attribName[CONST_ATTRIB_NAME_LENGTH]; glGetProgramiv(shaderProgram, GL_ACTIVE_ATTRIBUTES, &activeAttribs); for (int i = 0; i < activeAttribs; i++) { glGetActiveAttrib(shaderProgram, i, CONST_ATTRIB_NAME_LENGTH, &dummyLen, &dummySize, &dummyEnum, attribName); attribList[attribName] = glGetAttribLocation(shaderProgram, attribName); } } ShaderResource::~ShaderResource() { if (shaderProgram != 0) { glDeleteProgram(shaderProgram); shaderProgram = 0; } } GLuint ShaderResource::getShaderProgram() { return shaderProgram; } void ShaderManager::AddShaderFromFiles(const std::string& shaderName, const std::string& vertexShaderFileName, const std::string& fragmentShaderFileName, const std::string& ZIPFileName) { std::string vertexShader; std::string fragmentShader; if (!ZIPFileName.empty()){ std::vector vertexShaderData; std::vector fragmentShaderData; vertexShaderData = readFileFromZIP(vertexShaderFileName, ZIPFileName); fragmentShaderData = readFileFromZIP(fragmentShaderFileName, ZIPFileName); vertexShader = std::string(vertexShaderData.begin(), vertexShaderData.end()); fragmentShader = std::string(fragmentShaderData.begin(), fragmentShaderData.end()); }else{ vertexShader = readTextFile(vertexShaderFileName); fragmentShader = readTextFile(fragmentShaderFileName); } ///std::cout << "Shader: "<< vertexShader << std::endl; shaderResourceMap[shaderName] = std::make_shared(vertexShader, fragmentShader); } void ShaderManager::PushShader(const std::string& shaderName) { if (shaderStack.size() >= CONST_MAX_SHADER_STACK_SIZE) { throw std::runtime_error("Shader stack overflow!"); } if (shaderResourceMap.find(shaderName) == shaderResourceMap.end()) { throw std::runtime_error("Shader does not exist!"); } shaderStack.push(shaderName); glUseProgram(shaderResourceMap[shaderName]->getShaderProgram()); } void ShaderManager::PopShader() { if (shaderStack.size() == 0) { throw std::runtime_error("Shader stack underflow!"); } shaderStack.pop(); if (shaderStack.size() == 0) { glUseProgram(0); } else { glUseProgram(shaderResourceMap[shaderStack.top()]->getShaderProgram()); } } std::shared_ptr ShaderManager::GetCurrentShader() { if (shaderStack.size() == 0) { throw std::runtime_error("Shader stack underflow!"); } return shaderResourceMap[shaderStack.top()]; } ShaderSetter::ShaderSetter(ShaderManager& inShaderManager, const std::string& shaderName) : shaderManager(shaderManager) { shaderManager.PushShader(shaderName); } ShaderSetter::~ShaderSetter() { shaderManager.PopShader(); } }