222 lines
7.4 KiB
C++
222 lines
7.4 KiB
C++
#include "ShaderManager.h"
|
|
#include <iostream>
|
|
#include <SDL.h>
|
|
|
|
#ifdef __ANDROID__
|
|
#include <android/log.h>
|
|
#endif
|
|
|
|
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) {
|
|
#ifdef __ANDROID__
|
|
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
|
|
"Failed to compile vertex shader: %s", infoLog);
|
|
#endif
|
|
throw std::runtime_error("Failed to compile vertex shader code!");
|
|
}
|
|
|
|
if (!fragmentShaderCompiled) {
|
|
#ifdef __ANDROID__
|
|
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
|
|
"Failed to compile fragment shader: %s", infoLog);
|
|
#endif
|
|
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;
|
|
#ifdef __ANDROID__
|
|
__android_log_print(ANDROID_LOG_ERROR, "ShaderManager",
|
|
"Failed to link shader program: %s", infoLog);
|
|
#endif
|
|
throw std::runtime_error("Failed to link shader program!");
|
|
}
|
|
|
|
//================= Parsing all uniforms ================
|
|
|
|
int dummySize; //Dummy
|
|
int dummyLen; //Dummy
|
|
GLenum dummyEnum;
|
|
|
|
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);
|
|
}
|
|
|
|
#ifdef __ANDROID__
|
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
|
"Shader created successfully, program ID: %u", shaderProgram);
|
|
#endif
|
|
}
|
|
|
|
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) {
|
|
#ifdef __ANDROID__
|
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
|
"Loading shader: %s", shaderName.c_str());
|
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
|
"Vertex shader: %s", vertexShaderFileName.c_str());
|
|
__android_log_print(ANDROID_LOG_INFO, "ShaderManager",
|
|
"Fragment shader: %s", fragmentShaderFileName.c_str());
|
|
#endif
|
|
|
|
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(inShaderManager) {
|
|
shaderManager.PushShader(shaderName);
|
|
}
|
|
|
|
ShaderSetter::~ShaderSetter() {
|
|
shaderManager.PopShader();
|
|
}
|
|
|
|
} |