diff options
Diffstat (limited to 'src/render/Shader.cpp')
| -rw-r--r-- | src/render/Shader.cpp | 305 |
1 files changed, 253 insertions, 52 deletions
diff --git a/src/render/Shader.cpp b/src/render/Shader.cpp index 5081d4c4..635e1328 100644 --- a/src/render/Shader.cpp +++ b/src/render/Shader.cpp @@ -1,4 +1,5 @@ #include "Shader.hpp" +#include "../config/ConfigManager.hpp" #include "render/OpenGL.hpp" #define EPSILON(x, y) (std::abs((x) - (y)) < 1e-5f) @@ -14,51 +15,235 @@ static bool compareFloat(auto a, auto b) { return true; } -SShader::SShader() { - uniformLocations.fill(-1); +CShader::CShader() { + m_uniformLocations.fill(-1); } -SShader::~SShader() { +CShader::~CShader() { destroy(); } -void SShader::createVao() { +void CShader::logShaderError(const GLuint& shader, bool program, bool silent) { + GLint maxLength = 0; + if (program) + glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + else + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); + + std::vector<GLchar> errorLog(maxLength); + if (program) + glGetProgramInfoLog(shader, maxLength, &maxLength, errorLog.data()); + else + glGetShaderInfoLog(shader, maxLength, &maxLength, errorLog.data()); + std::string errorStr(errorLog.begin(), errorLog.end()); + + const auto FULLERROR = (program ? "Screen shader parser: Error linking program:" : "Screen shader parser: Error compiling shader: ") + errorStr; + + Log::logger->log(Log::ERR, "Failed to link shader: {}", FULLERROR); + + if (!silent) + g_pConfigManager->addParseError(FULLERROR); +} + +GLuint CShader::compileShader(const GLuint& type, std::string src, bool dynamic, bool silent) { + auto shader = glCreateShader(type); + + auto shaderSource = src.c_str(); + + glShaderSource(shader, 1, &shaderSource, nullptr); + glCompileShader(shader); + + GLint ok; + glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); + + if (dynamic) { + if (ok == GL_FALSE) { + logShaderError(shader, false, silent); + return 0; + } + } else { + if (ok != GL_TRUE) + logShaderError(shader, false); + RASSERT(ok != GL_FALSE, "compileShader() failed! GL_COMPILE_STATUS not OK!"); + } + + return shader; +} + +bool CShader::createProgram(const std::string& vert, const std::string& frag, bool dynamic, bool silent) { + auto vertCompiled = compileShader(GL_VERTEX_SHADER, vert, dynamic, silent); + if (dynamic) { + if (vertCompiled == 0) + return false; + } else + RASSERT(vertCompiled, "Compiling shader failed. VERTEX nullptr! Shader source:\n\n{}", vert); + + auto fragCompiled = compileShader(GL_FRAGMENT_SHADER, frag, dynamic, silent); + if (dynamic) { + if (fragCompiled == 0) + return false; + } else + RASSERT(fragCompiled, "Compiling shader failed. FRAGMENT nullptr! Shader source:\n\n{}", frag); + + auto prog = glCreateProgram(); + glAttachShader(prog, vertCompiled); + glAttachShader(prog, fragCompiled); + glLinkProgram(prog); + + glDetachShader(prog, vertCompiled); + glDetachShader(prog, fragCompiled); + glDeleteShader(vertCompiled); + glDeleteShader(fragCompiled); + + GLint ok; + glGetProgramiv(prog, GL_LINK_STATUS, &ok); + if (dynamic) { + if (ok == GL_FALSE) { + logShaderError(prog, true, silent); + return false; + } + } else { + if (ok != GL_TRUE) + logShaderError(prog, true); + RASSERT(ok != GL_FALSE, "createProgram() failed! GL_LINK_STATUS not OK!"); + } + + m_program = prog; + + getUniformLocations(); + createVao(); + return true; +} + +// its fine to call glGet on shaders that dont have the uniform +// this however hardcodes the name now. #TODO maybe dont +void CShader::getUniformLocations() { + auto getUniform = [this](const GLchar* name) { return glGetUniformLocation(m_program, name); }; + auto getAttrib = [this](const GLchar* name) { return glGetAttribLocation(m_program, name); }; + + m_uniformLocations[SHADER_PROJ] = getUniform("proj"); + m_uniformLocations[SHADER_COLOR] = getUniform("color"); + m_uniformLocations[SHADER_ALPHA_MATTE] = getUniform("texMatte"); + m_uniformLocations[SHADER_TEX_TYPE] = getUniform("texType"); + + // shader has #include "CM.glsl" + m_uniformLocations[SHADER_SKIP_CM] = getUniform("skipCM"); + m_uniformLocations[SHADER_SOURCE_TF] = getUniform("sourceTF"); + m_uniformLocations[SHADER_TARGET_TF] = getUniform("targetTF"); + m_uniformLocations[SHADER_SRC_TF_RANGE] = getUniform("srcTFRange"); + m_uniformLocations[SHADER_DST_TF_RANGE] = getUniform("dstTFRange"); + m_uniformLocations[SHADER_TARGET_PRIMARIES] = getUniform("targetPrimaries"); + m_uniformLocations[SHADER_MAX_LUMINANCE] = getUniform("maxLuminance"); + m_uniformLocations[SHADER_SRC_REF_LUMINANCE] = getUniform("srcRefLuminance"); + m_uniformLocations[SHADER_DST_MAX_LUMINANCE] = getUniform("dstMaxLuminance"); + m_uniformLocations[SHADER_DST_REF_LUMINANCE] = getUniform("dstRefLuminance"); + m_uniformLocations[SHADER_SDR_SATURATION] = getUniform("sdrSaturation"); + m_uniformLocations[SHADER_SDR_BRIGHTNESS] = getUniform("sdrBrightnessMultiplier"); + m_uniformLocations[SHADER_CONVERT_MATRIX] = getUniform("convertMatrix"); + // + m_uniformLocations[SHADER_TEX] = getUniform("tex"); + m_uniformLocations[SHADER_ALPHA] = getUniform("alpha"); + m_uniformLocations[SHADER_POS_ATTRIB] = getAttrib("pos"); + m_uniformLocations[SHADER_TEX_ATTRIB] = getAttrib("texcoord"); + m_uniformLocations[SHADER_MATTE_TEX_ATTRIB] = getAttrib("texcoordMatte"); + m_uniformLocations[SHADER_DISCARD_OPAQUE] = getUniform("discardOpaque"); + m_uniformLocations[SHADER_DISCARD_ALPHA] = getUniform("discardAlpha"); + m_uniformLocations[SHADER_DISCARD_ALPHA_VALUE] = getUniform("discardAlphaValue"); + /* set in createVao + m_uniformLocations[SHADER_SHADER_VAO] + m_uniformLocations[SHADER_SHADER_VBO_POS] + m_uniformLocations[SHADER_SHADER_VBO_UV] + */ + m_uniformLocations[SHADER_TOP_LEFT] = getUniform("topLeft"); + m_uniformLocations[SHADER_BOTTOM_RIGHT] = getUniform("bottomRight"); + + // compat for screenshaders + auto fullSize = getUniform("fullSize"); + if (fullSize == -1) + fullSize = getUniform("screen_size"); + if (fullSize == -1) + fullSize = getUniform("screenSize"); + m_uniformLocations[SHADER_FULL_SIZE] = fullSize; + + m_uniformLocations[SHADER_FULL_SIZE_UNTRANSFORMED] = getUniform("fullSizeUntransformed"); + m_uniformLocations[SHADER_RADIUS] = getUniform("radius"); + m_uniformLocations[SHADER_RADIUS_OUTER] = getUniform("radiusOuter"); + m_uniformLocations[SHADER_ROUNDING_POWER] = getUniform("roundingPower"); + m_uniformLocations[SHADER_THICK] = getUniform("thick"); + m_uniformLocations[SHADER_HALFPIXEL] = getUniform("halfpixel"); + m_uniformLocations[SHADER_RANGE] = getUniform("range"); + m_uniformLocations[SHADER_SHADOW_POWER] = getUniform("shadowPower"); + m_uniformLocations[SHADER_USE_ALPHA_MATTE] = getUniform("useAlphaMatte"); + m_uniformLocations[SHADER_APPLY_TINT] = getUniform("applyTint"); + m_uniformLocations[SHADER_TINT] = getUniform("tint"); + m_uniformLocations[SHADER_GRADIENT] = getUniform("gradient"); + m_uniformLocations[SHADER_GRADIENT_LENGTH] = getUniform("gradientLength"); + m_uniformLocations[SHADER_GRADIENT2] = getUniform("gradient2"); + m_uniformLocations[SHADER_GRADIENT2_LENGTH] = getUniform("gradient2Length"); + m_uniformLocations[SHADER_ANGLE] = getUniform("angle"); + m_uniformLocations[SHADER_ANGLE2] = getUniform("angle2"); + m_uniformLocations[SHADER_GRADIENT_LERP] = getUniform("gradientLerp"); + m_uniformLocations[SHADER_TIME] = getUniform("time"); + m_uniformLocations[SHADER_DISTORT] = getUniform("distort"); + m_uniformLocations[SHADER_WL_OUTPUT] = getUniform("wl_output"); + m_uniformLocations[SHADER_CONTRAST] = getUniform("contrast"); + m_uniformLocations[SHADER_PASSES] = getUniform("passes"); + m_uniformLocations[SHADER_VIBRANCY] = getUniform("vibrancy"); + m_uniformLocations[SHADER_VIBRANCY_DARKNESS] = getUniform("vibrancy_darkness"); + m_uniformLocations[SHADER_BRIGHTNESS] = getUniform("brightness"); + m_uniformLocations[SHADER_NOISE] = getUniform("noise"); + m_uniformLocations[SHADER_POINTER] = getUniform("pointer_position"); + m_uniformLocations[SHADER_POINTER_SHAPE] = getUniform("pointer_shape"); + m_uniformLocations[SHADER_POINTER_SWITCH_TIME] = getUniform("pointer_switch_time"); + m_uniformLocations[SHADER_POINTER_SHAPE_PREVIOUS] = getUniform("pointer_shape_previous"); + m_uniformLocations[SHADER_POINTER_PRESSED_POSITIONS] = getUniform("pointer_pressed_positions"); + m_uniformLocations[SHADER_POINTER_HIDDEN] = getUniform("pointer_hidden"); + m_uniformLocations[SHADER_POINTER_KILLING] = getUniform("pointer_killing"); + m_uniformLocations[SHADER_POINTER_PRESSED_TIMES] = getUniform("pointer_pressed_times"); + m_uniformLocations[SHADER_POINTER_PRESSED_KILLED] = getUniform("pointer_pressed_killed"); + m_uniformLocations[SHADER_POINTER_PRESSED_TOUCHED] = getUniform("pointer_pressed_touched"); + m_uniformLocations[SHADER_POINTER_INACTIVE_TIMEOUT] = getUniform("pointer_inactive_timeout"); + m_uniformLocations[SHADER_POINTER_LAST_ACTIVE] = getUniform("pointer_last_active"); + m_uniformLocations[SHADER_POINTER_SIZE] = getUniform("pointer_size"); +} + +void CShader::createVao() { GLuint shaderVao = 0, shaderVbo = 0, shaderVboUv = 0; glGenVertexArrays(1, &shaderVao); glBindVertexArray(shaderVao); - if (uniformLocations[SHADER_POS_ATTRIB] != -1) { + if (m_uniformLocations[SHADER_POS_ATTRIB] != -1) { glGenBuffers(1, &shaderVbo); glBindBuffer(GL_ARRAY_BUFFER, shaderVbo); glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_STATIC_DRAW); - glEnableVertexAttribArray(uniformLocations[SHADER_POS_ATTRIB]); - glVertexAttribPointer(uniformLocations[SHADER_POS_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_uniformLocations[SHADER_POS_ATTRIB]); + glVertexAttribPointer(m_uniformLocations[SHADER_POS_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); } // UV VBO (dynamic, may be updated per frame) - if (uniformLocations[SHADER_TEX_ATTRIB] != -1) { + if (m_uniformLocations[SHADER_TEX_ATTRIB] != -1) { glGenBuffers(1, &shaderVboUv); glBindBuffer(GL_ARRAY_BUFFER, shaderVboUv); glBufferData(GL_ARRAY_BUFFER, sizeof(fullVerts), fullVerts, GL_DYNAMIC_DRAW); // Initial dummy UVs - glEnableVertexAttribArray(uniformLocations[SHADER_TEX_ATTRIB]); - glVertexAttribPointer(uniformLocations[SHADER_TEX_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); + glEnableVertexAttribArray(m_uniformLocations[SHADER_TEX_ATTRIB]); + glVertexAttribPointer(m_uniformLocations[SHADER_TEX_ATTRIB], 2, GL_FLOAT, GL_FALSE, 0, nullptr); } glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); - uniformLocations[SHADER_SHADER_VAO] = shaderVao; - uniformLocations[SHADER_SHADER_VBO_POS] = shaderVbo; - uniformLocations[SHADER_SHADER_VBO_UV] = shaderVboUv; + m_uniformLocations[SHADER_SHADER_VAO] = shaderVao; + m_uniformLocations[SHADER_SHADER_VBO_POS] = shaderVbo; + m_uniformLocations[SHADER_SHADER_VBO_UV] = shaderVboUv; - RASSERT(uniformLocations[SHADER_SHADER_VAO] >= 0, "SHADER_SHADER_VAO could not be created"); - RASSERT(uniformLocations[SHADER_SHADER_VBO_POS] >= 0, "SHADER_SHADER_VBO_POS could not be created"); - RASSERT(uniformLocations[SHADER_SHADER_VBO_UV] >= 0, "SHADER_SHADER_VBO_UV could not be created"); + RASSERT(m_uniformLocations[SHADER_SHADER_VAO] >= 0, "SHADER_SHADER_VAO could not be created"); + RASSERT(m_uniformLocations[SHADER_SHADER_VBO_POS] >= 0, "SHADER_SHADER_VBO_POS could not be created"); + RASSERT(m_uniformLocations[SHADER_SHADER_VBO_UV] >= 0, "SHADER_SHADER_VBO_UV could not be created"); } -void SShader::setUniformInt(eShaderUniform location, GLint v0) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformInt(eShaderUniform location, GLint v0) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -67,11 +252,11 @@ void SShader::setUniformInt(eShaderUniform location, GLint v0) { return; cached = v0; - glUniform1i(uniformLocations[location], v0); + glUniform1i(m_uniformLocations[location], v0); } -void SShader::setUniformFloat(eShaderUniform location, GLfloat v0) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat(eShaderUniform location, GLfloat v0) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -83,11 +268,11 @@ void SShader::setUniformFloat(eShaderUniform location, GLfloat v0) { } cached = v0; - glUniform1f(uniformLocations[location], v0); + glUniform1f(m_uniformLocations[location], v0); } -void SShader::setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -99,11 +284,11 @@ void SShader::setUniformFloat2(eShaderUniform location, GLfloat v0, GLfloat v1) } cached = std::array<GLfloat, 2>{v0, v1}; - glUniform2f(uniformLocations[location], v0, v1); + glUniform2f(m_uniformLocations[location], v0, v1); } -void SShader::setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -115,11 +300,11 @@ void SShader::setUniformFloat3(eShaderUniform location, GLfloat v0, GLfloat v1, } cached = std::array<GLfloat, 3>{v0, v1, v2}; - glUniform3f(uniformLocations[location], v0, v1, v2); + glUniform3f(m_uniformLocations[location], v0, v1, v2); } -void SShader::setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -131,11 +316,11 @@ void SShader::setUniformFloat4(eShaderUniform location, GLfloat v0, GLfloat v1, } cached = std::array<GLfloat, 4>{v0, v1, v2, v3}; - glUniform4f(uniformLocations[location], v0, v1, v2, v3); + glUniform4f(m_uniformLocations[location], v0, v1, v2, v3); } -void SShader::setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array<GLfloat, 9> value) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array<GLfloat, 9> value) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -147,11 +332,11 @@ void SShader::setUniformMatrix3fv(eShaderUniform location, GLsizei count, GLbool } cached = SUniformMatrix3Data{.count = count, .transpose = transpose, .value = value}; - glUniformMatrix3fv(uniformLocations[location], count, transpose, value.data()); + glUniformMatrix3fv(m_uniformLocations[location], count, transpose, value.data()); } -void SShader::setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array<GLfloat, 8> value) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLboolean transpose, std::array<GLfloat, 8> value) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -163,11 +348,11 @@ void SShader::setUniformMatrix4x2fv(eShaderUniform location, GLsizei count, GLbo } cached = SUniformMatrix4Data{.count = count, .transpose = transpose, .value = value}; - glUniformMatrix4x2fv(uniformLocations[location], count, transpose, value.data()); + glUniformMatrix4x2fv(m_uniformLocations[location], count, transpose, value.data()); } -void SShader::setUniformfv(eShaderUniform location, GLsizei count, const std::vector<float>& value, GLsizei vec_size) { - if (uniformLocations.at(location) == -1) +void CShader::setUniformfv(eShaderUniform location, GLsizei count, const std::vector<float>& value, GLsizei vec_size) { + if (m_uniformLocations.at(location) == -1) return; auto& cached = uniformStatus.at(location); @@ -180,36 +365,36 @@ void SShader::setUniformfv(eShaderUniform location, GLsizei count, const std::ve cached = SUniformVData{.count = count, .value = value}; switch (vec_size) { - case 1: glUniform1fv(uniformLocations[location], count, value.data()); break; - case 2: glUniform2fv(uniformLocations[location], count, value.data()); break; - case 4: glUniform4fv(uniformLocations[location], count, value.data()); break; + case 1: glUniform1fv(m_uniformLocations[location], count, value.data()); break; + case 2: glUniform2fv(m_uniformLocations[location], count, value.data()); break; + case 4: glUniform4fv(m_uniformLocations[location], count, value.data()); break; default: UNREACHABLE(); } } -void SShader::setUniform1fv(eShaderUniform location, GLsizei count, const std::vector<float>& value) { +void CShader::setUniform1fv(eShaderUniform location, GLsizei count, const std::vector<float>& value) { setUniformfv(location, count, value, 1); } -void SShader::setUniform2fv(eShaderUniform location, GLsizei count, const std::vector<float>& value) { +void CShader::setUniform2fv(eShaderUniform location, GLsizei count, const std::vector<float>& value) { setUniformfv(location, count, value, 2); } -void SShader::setUniform4fv(eShaderUniform location, GLsizei count, const std::vector<float>& value) { +void CShader::setUniform4fv(eShaderUniform location, GLsizei count, const std::vector<float>& value) { setUniformfv(location, count, value, 4); } -void SShader::destroy() { +void CShader::destroy() { uniformStatus.fill(std::monostate()); - if (program == 0) + if (m_program == 0) return; GLuint shaderVao, shaderVbo, shaderVboUv; - shaderVao = uniformLocations[SHADER_SHADER_VAO] == -1 ? 0 : uniformLocations[SHADER_SHADER_VAO]; - shaderVbo = uniformLocations[SHADER_SHADER_VBO_POS] == -1 ? 0 : uniformLocations[SHADER_SHADER_VBO_POS]; - shaderVboUv = uniformLocations[SHADER_SHADER_VBO_UV] == -1 ? 0 : uniformLocations[SHADER_SHADER_VBO_UV]; + shaderVao = m_uniformLocations[SHADER_SHADER_VAO] == -1 ? 0 : m_uniformLocations[SHADER_SHADER_VAO]; + shaderVbo = m_uniformLocations[SHADER_SHADER_VBO_POS] == -1 ? 0 : m_uniformLocations[SHADER_SHADER_VBO_POS]; + shaderVboUv = m_uniformLocations[SHADER_SHADER_VBO_UV] == -1 ? 0 : m_uniformLocations[SHADER_SHADER_VBO_UV]; if (shaderVao) glDeleteVertexArrays(1, &shaderVao); @@ -220,6 +405,22 @@ void SShader::destroy() { if (shaderVboUv) glDeleteBuffers(1, &shaderVboUv); - glDeleteProgram(program); - program = 0; + glDeleteProgram(m_program); + m_program = 0; +} + +GLint CShader::getUniformLocation(eShaderUniform location) const { + return m_uniformLocations[location]; +} + +GLuint CShader::program() const { + return m_program; +} + +int CShader::getInitialTime() const { + return m_initialTime; +} + +void CShader::setInitialTime(int time) { + m_initialTime = time; } |
