212 lines
5.5 KiB
C++
Executable File
212 lines
5.5 KiB
C++
Executable File
#include "ShaderManager.h"
|
|
#include <iostream>
|
|
|
|
|
|
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<int>(strlen(vertexCode.c_str()));
|
|
int fragmentCodeLength = static_cast<int>(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!");
|
|
}
|
|
|
|
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<char> vertexShaderData;
|
|
std::vector<char> 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<ShaderResource>(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<ShaderResource> 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();
|
|
}
|
|
|
|
} |