2019-08-12 06:33:40 +00:00
|
|
|
|
|
|
|
#include "Precomp.h"
|
|
|
|
#include "Shader.h"
|
|
|
|
#include "RenderDevice.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
|
2019-12-15 21:53:33 +00:00
|
|
|
void Shader::Setup(const std::string& identifier, const std::string& vertexShader, const std::string& fragmentShader, bool alphatest)
|
2019-08-12 06:33:40 +00:00
|
|
|
{
|
2019-12-15 21:53:33 +00:00
|
|
|
mIdentifier = identifier;
|
2019-08-22 13:46:24 +00:00
|
|
|
mVertexText = vertexShader;
|
|
|
|
mFragmentText = fragmentShader;
|
|
|
|
mAlphatest = alphatest;
|
2019-08-12 06:33:40 +00:00
|
|
|
}
|
|
|
|
|
2019-12-15 21:53:33 +00:00
|
|
|
bool Shader::CheckCompile()
|
2019-08-22 13:46:24 +00:00
|
|
|
{
|
|
|
|
bool firstCall = !mProgramBuilt;
|
|
|
|
if (firstCall)
|
|
|
|
{
|
|
|
|
mProgramBuilt = true;
|
|
|
|
CreateProgram();
|
2019-12-15 21:53:33 +00:00
|
|
|
glUseProgram(mProgram);
|
|
|
|
glUniform1i(glGetUniformLocation(mProgram, "texture1"), 0);
|
|
|
|
glUseProgram(0);
|
2019-08-22 13:46:24 +00:00
|
|
|
}
|
|
|
|
|
2019-12-15 21:53:33 +00:00
|
|
|
return !mErrors.size();
|
|
|
|
}
|
2019-08-22 13:46:24 +00:00
|
|
|
|
2019-12-15 21:53:33 +00:00
|
|
|
std::string Shader::GetCompileError()
|
|
|
|
{
|
|
|
|
std::string lines = "Error compiling ";
|
|
|
|
if (!mVertexShader)
|
|
|
|
lines += "vertex ";
|
|
|
|
else if (!mFragmentShader)
|
|
|
|
lines += "fragment ";
|
|
|
|
lines += "shader \"" + mIdentifier + "\":\r\n";
|
|
|
|
for (auto c : mErrors)
|
2019-08-22 13:46:24 +00:00
|
|
|
{
|
2019-12-15 21:53:33 +00:00
|
|
|
if (c == '\r')
|
|
|
|
continue;
|
|
|
|
if (c == '\n')
|
|
|
|
lines += "\r\n";
|
|
|
|
else lines += c;
|
2019-08-22 13:46:24 +00:00
|
|
|
}
|
2019-12-15 21:53:33 +00:00
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shader::Bind()
|
|
|
|
{
|
|
|
|
if (!mProgram || !mProgramBuilt || mErrors.size())
|
|
|
|
return;
|
|
|
|
|
|
|
|
glUseProgram(mProgram);
|
2019-08-22 13:46:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Shader::CreateProgram()
|
2019-08-12 06:33:40 +00:00
|
|
|
{
|
2019-08-16 02:10:03 +00:00
|
|
|
const char* prefixNAT = R"(
|
|
|
|
#version 150
|
|
|
|
#line 1
|
|
|
|
)";
|
|
|
|
const char* prefixAT = R"(
|
|
|
|
#version 150
|
|
|
|
#define ALPHA_TEST
|
|
|
|
#line 1
|
|
|
|
)";
|
|
|
|
|
2019-08-22 13:46:24 +00:00
|
|
|
const char* prefix = mAlphatest ? prefixAT : prefixNAT;
|
2019-08-16 02:10:03 +00:00
|
|
|
|
2019-08-22 13:46:24 +00:00
|
|
|
mVertexShader = CompileShader(prefix + mVertexText, GL_VERTEX_SHADER);
|
2019-08-12 06:33:40 +00:00
|
|
|
if (!mVertexShader)
|
2019-08-22 13:46:24 +00:00
|
|
|
return;
|
2019-08-12 06:33:40 +00:00
|
|
|
|
2019-08-22 13:46:24 +00:00
|
|
|
mFragmentShader = CompileShader(prefix + mFragmentText, GL_FRAGMENT_SHADER);
|
2019-08-12 06:33:40 +00:00
|
|
|
if (!mFragmentShader)
|
2019-08-22 13:46:24 +00:00
|
|
|
return;
|
2019-08-12 06:33:40 +00:00
|
|
|
|
|
|
|
mProgram = glCreateProgram();
|
|
|
|
glAttachShader(mProgram, mVertexShader);
|
|
|
|
glAttachShader(mProgram, mFragmentShader);
|
|
|
|
glBindAttribLocation(mProgram, (GLuint)DeclarationUsage::Position, "AttrPosition");
|
|
|
|
glBindAttribLocation(mProgram, (GLuint)DeclarationUsage::Color, "AttrColor");
|
|
|
|
glBindAttribLocation(mProgram, (GLuint)DeclarationUsage::TextureCoordinate, "AttrUV");
|
|
|
|
glBindAttribLocation(mProgram, (GLuint)DeclarationUsage::Normal, "AttrNormal");
|
|
|
|
glLinkProgram(mProgram);
|
|
|
|
|
|
|
|
GLint status = 0;
|
|
|
|
glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
|
|
|
|
if (status != GL_TRUE)
|
|
|
|
{
|
|
|
|
GLsizei length = 0;
|
|
|
|
glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &length);
|
|
|
|
std::vector<GLchar> errors(length + (size_t)1);
|
|
|
|
glGetProgramInfoLog(mProgram, (GLsizei)errors.size(), &length, errors.data());
|
|
|
|
mErrors = { errors.begin(), errors.begin() + length };
|
|
|
|
|
|
|
|
glDeleteProgram(mProgram);
|
|
|
|
glDeleteShader(mVertexShader);
|
|
|
|
glDeleteShader(mFragmentShader);
|
|
|
|
mProgram = 0;
|
|
|
|
mVertexShader = 0;
|
|
|
|
mFragmentShader = 0;
|
2019-08-22 13:46:24 +00:00
|
|
|
return;
|
2019-08-12 06:33:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-14 10:36:33 +00:00
|
|
|
static const char* names[(int)UniformName::NumUniforms] = {
|
|
|
|
"rendersettings",
|
2019-08-22 16:43:54 +00:00
|
|
|
"projection",
|
2019-08-14 10:36:33 +00:00
|
|
|
"desaturation",
|
|
|
|
"highlightcolor",
|
2019-08-22 16:43:54 +00:00
|
|
|
"view",
|
2019-08-14 10:36:33 +00:00
|
|
|
"world",
|
|
|
|
"modelnormal",
|
|
|
|
"fillColor",
|
|
|
|
"vertexColor",
|
|
|
|
"stencilColor",
|
|
|
|
"lightPosAndRadius",
|
|
|
|
"lightOrientation",
|
|
|
|
"light2Radius",
|
|
|
|
"lightColor",
|
|
|
|
"ignoreNormals",
|
|
|
|
"spotLight",
|
2019-08-16 12:01:27 +00:00
|
|
|
"campos",
|
2019-08-22 16:43:54 +00:00
|
|
|
"texturefactor",
|
|
|
|
"fogsettings",
|
|
|
|
"fogcolor"
|
2019-08-14 10:36:33 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; i < (int)UniformName::NumUniforms; i++)
|
|
|
|
{
|
|
|
|
UniformLocations[i] = glGetUniformLocation(mProgram, names[i]);
|
|
|
|
}
|
2019-08-12 06:33:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GLuint Shader::CompileShader(const std::string& code, GLenum type)
|
|
|
|
{
|
|
|
|
GLuint shader = glCreateShader(type);
|
|
|
|
const GLchar* sources[] = { (GLchar*)code.data() };
|
|
|
|
const GLint lengths[] = { (GLint)code.size() };
|
|
|
|
glShaderSource(shader, 1, sources, lengths);
|
|
|
|
glCompileShader(shader);
|
|
|
|
|
|
|
|
GLint status = 0;
|
|
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
|
|
|
if (status != GL_TRUE)
|
|
|
|
{
|
|
|
|
GLsizei length = 0;
|
|
|
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
|
|
|
|
std::vector<GLchar> errors(length + (size_t)1);
|
|
|
|
glGetShaderInfoLog(shader, (GLsizei)errors.size(), &length, errors.data());
|
|
|
|
mErrors = { errors.begin(), errors.begin() + length };
|
|
|
|
glDeleteShader(shader);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return shader;
|
|
|
|
}
|
2019-08-22 13:46:24 +00:00
|
|
|
|
|
|
|
void Shader::ReleaseResources()
|
|
|
|
{
|
|
|
|
if (mProgram)
|
|
|
|
glDeleteProgram(mProgram);
|
|
|
|
if (mVertexShader)
|
|
|
|
glDeleteShader(mVertexShader);
|
|
|
|
if (mFragmentShader)
|
|
|
|
glDeleteShader(mFragmentShader);
|
|
|
|
mProgram = 0;
|
|
|
|
mVertexShader = 0;
|
|
|
|
mFragmentShader = 0;
|
|
|
|
}
|