2020-09-16 20:14:35 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-08-30 20:19:37 +00:00
|
|
|
//
|
2020-09-16 20:14:35 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2022-03-14 19:14:18 +00:00
|
|
|
// ShaderOpenGL.cpp
|
2020-08-30 20:19:37 +00:00
|
|
|
//
|
2022-03-14 19:14:18 +00:00
|
|
|
// OpenGL / OpenGL ES shader functions.
|
2020-08-30 20:19:37 +00:00
|
|
|
//
|
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
#include "ShaderOpenGL.h"
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2021-07-07 18:31:46 +00:00
|
|
|
#include "Log.h"
|
2020-08-30 20:19:37 +00:00
|
|
|
#include "renderers/Renderer.h"
|
|
|
|
#include "resources/ResourceManager.h"
|
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
ShaderOpenGL::ShaderOpenGL()
|
2022-03-14 18:51:48 +00:00
|
|
|
: mProgramID {0}
|
|
|
|
, mShaderMVPMatrix {0}
|
|
|
|
, mShaderPosition {0}
|
|
|
|
, mShaderTextureCoord {0}
|
|
|
|
, mShaderColor {0}
|
|
|
|
, mShaderTextureSize {0}
|
|
|
|
, mShaderOpacity {0}
|
|
|
|
, mShaderSaturation {0}
|
|
|
|
, mShaderDimming {0}
|
|
|
|
, mShaderBGRAToRGBA {0}
|
|
|
|
, mShaderFont {0}
|
|
|
|
, mShaderPostProcessing {0}
|
2020-08-30 20:19:37 +00:00
|
|
|
{
|
2022-03-14 18:51:48 +00:00
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
ShaderOpenGL::~ShaderOpenGL()
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
// Delete the shader program when destroyed.
|
|
|
|
deleteProgram(mProgramID);
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::loadShaderFile(const std::string& path, GLenum shaderType)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
std::string preprocessorDefines;
|
|
|
|
std::string shaderCode;
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
// This will load the entire GLSL source code into the string variable.
|
|
|
|
const ResourceData& shaderData {ResourceManager::getInstance().getFileData(path)};
|
|
|
|
shaderCode.assign(reinterpret_cast<const char*>(shaderData.ptr.get()), shaderData.length);
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
// Define the GLSL version.
|
2022-03-13 22:52:32 +00:00
|
|
|
#if defined(USE_OPENGLES)
|
2022-03-14 18:51:48 +00:00
|
|
|
preprocessorDefines = "#version 300 es\n";
|
2022-03-13 22:52:32 +00:00
|
|
|
#else
|
2022-03-14 18:51:48 +00:00
|
|
|
preprocessorDefines = "#version 330\n";
|
2022-03-13 22:52:32 +00:00
|
|
|
#endif
|
2022-03-14 18:51:48 +00:00
|
|
|
// Define the preprocessor constants that will let the shader compiler know whether
|
|
|
|
// the VERTEX or FRAGMENT portion of the code should be used.
|
|
|
|
if (shaderType == GL_VERTEX_SHADER)
|
|
|
|
preprocessorDefines += "#define VERTEX\n";
|
|
|
|
else if (shaderType == GL_FRAGMENT_SHADER)
|
|
|
|
preprocessorDefines += "#define FRAGMENT\n";
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
mShaderVector.push_back(std::make_tuple(path, preprocessorDefines + shaderCode, shaderType));
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
bool ShaderOpenGL::createProgram()
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
GLint programSuccess;
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
mProgramID = glCreateProgram();
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
// Compile and attach all shaders that have been loaded.
|
|
|
|
for (auto it = mShaderVector.cbegin(); it != mShaderVector.cend(); ++it) {
|
|
|
|
GLuint currentShader {glCreateShader(std::get<2>(*it))};
|
|
|
|
GLchar const* shaderCodePtr {std::get<1>(*it).c_str()};
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
glShaderSource(currentShader, 1, reinterpret_cast<const GLchar**>(&shaderCodePtr), nullptr);
|
|
|
|
glCompileShader(currentShader);
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
GLint shaderCompiled;
|
|
|
|
glGetShaderiv(currentShader, GL_COMPILE_STATUS, &shaderCompiled);
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
if (shaderCompiled != GL_TRUE) {
|
|
|
|
LOG(LogError) << "OpenGL error: Unable to compile shader " << currentShader << " ("
|
|
|
|
<< std::get<0>(*it) << ").";
|
|
|
|
printShaderInfoLog(currentShader, std::get<2>(*it), true);
|
2020-08-30 20:19:37 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-03-14 18:51:48 +00:00
|
|
|
else {
|
|
|
|
printShaderInfoLog(currentShader, std::get<2>(*it), false);
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
GL_CHECK_ERROR(glAttachShader(mProgramID, currentShader));
|
|
|
|
}
|
2022-03-13 22:52:32 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
glLinkProgram(mProgramID);
|
2022-03-13 22:52:32 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
glGetProgramiv(mProgramID, GL_LINK_STATUS, &programSuccess);
|
|
|
|
if (programSuccess != GL_TRUE) {
|
|
|
|
LOG(LogError) << "OpenGL error: Unable to link program " << mProgramID << ".";
|
|
|
|
printProgramInfoLog(mProgramID);
|
|
|
|
return false;
|
|
|
|
}
|
2022-03-13 22:52:32 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
getVariableLocations(mProgramID);
|
2022-03-13 22:52:32 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
if (mShaderPosition != -1)
|
|
|
|
GL_CHECK_ERROR(glEnableVertexAttribArray(mShaderPosition));
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
if (mShaderTextureCoord != -1)
|
|
|
|
GL_CHECK_ERROR(glEnableVertexAttribArray(mShaderTextureCoord));
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
if (mShaderColor != -1)
|
|
|
|
GL_CHECK_ERROR(glEnableVertexAttribArray(mShaderColor));
|
2020-09-12 10:14:48 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
return true;
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::deleteProgram(GLuint programID) { GL_CHECK_ERROR(glDeleteProgram(programID)); }
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::getVariableLocations(GLuint programID)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
// Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders.
|
|
|
|
mShaderMVPMatrix = glGetUniformLocation(mProgramID, "MVPMatrix");
|
|
|
|
mShaderPosition = glGetAttribLocation(mProgramID, "positionAttrib");
|
|
|
|
mShaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord");
|
|
|
|
mShaderColor = glGetAttribLocation(mProgramID, "colorAttrib");
|
|
|
|
mShaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize");
|
|
|
|
mShaderOpacity = glGetUniformLocation(mProgramID, "opacity");
|
|
|
|
mShaderSaturation = glGetUniformLocation(mProgramID, "saturation");
|
|
|
|
mShaderDimming = glGetUniformLocation(mProgramID, "dimming");
|
|
|
|
mShaderBGRAToRGBA = glGetUniformLocation(mProgramID, "BGRAToRGBA");
|
|
|
|
mShaderFont = glGetUniformLocation(mProgramID, "font");
|
|
|
|
mShaderPostProcessing = glGetUniformLocation(mProgramID, "postProcessing");
|
|
|
|
}
|
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setModelViewProjectionMatrix(glm::mat4 mvpMatrix)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderMVPMatrix != GL_INVALID_VALUE && mShaderMVPMatrix != GL_INVALID_OPERATION)
|
|
|
|
GL_CHECK_ERROR(glUniformMatrix4fv(mShaderMVPMatrix, 1, GL_FALSE,
|
|
|
|
reinterpret_cast<GLfloat*>(&mvpMatrix)));
|
|
|
|
}
|
2020-09-04 16:59:19 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setAttribPointers()
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderPosition != -1)
|
|
|
|
GL_CHECK_ERROR(glVertexAttribPointer(
|
|
|
|
mShaderPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer::Vertex),
|
|
|
|
reinterpret_cast<const void*>(offsetof(Renderer::Vertex, position))));
|
|
|
|
if (mShaderTextureCoord != -1)
|
|
|
|
GL_CHECK_ERROR(glVertexAttribPointer(
|
|
|
|
mShaderTextureCoord, 2, GL_FLOAT, GL_FALSE, sizeof(Renderer::Vertex),
|
|
|
|
reinterpret_cast<const void*>(offsetof(Renderer::Vertex, texture))));
|
|
|
|
|
|
|
|
if (mShaderColor != -1)
|
|
|
|
GL_CHECK_ERROR(glVertexAttribPointer(
|
|
|
|
mShaderColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(Renderer::Vertex),
|
|
|
|
reinterpret_cast<const void*>(offsetof(Renderer::Vertex, color))));
|
|
|
|
}
|
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setTextureSize(std::array<GLfloat, 2> shaderVec2)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderTextureSize != -1)
|
|
|
|
GL_CHECK_ERROR(glUniform2f(mShaderTextureSize, shaderVec2[0], shaderVec2[1]));
|
|
|
|
}
|
2020-09-04 16:59:19 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setOpacity(GLfloat opacity)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderOpacity != -1)
|
|
|
|
GL_CHECK_ERROR(glUniform1f(mShaderOpacity, opacity));
|
|
|
|
}
|
2020-09-12 10:14:48 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setSaturation(GLfloat saturation)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderSaturation != -1)
|
|
|
|
GL_CHECK_ERROR(glUniform1f(mShaderSaturation, saturation));
|
|
|
|
}
|
2020-09-12 17:17:26 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setDimming(GLfloat dimming)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderDimming != -1)
|
|
|
|
GL_CHECK_ERROR(glUniform1f(mShaderDimming, dimming));
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setBGRAToRGBA(GLboolean BGRAToRGBA)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderBGRAToRGBA != -1)
|
|
|
|
GL_CHECK_ERROR(glUniform1i(mShaderBGRAToRGBA, BGRAToRGBA ? 1 : 0));
|
|
|
|
}
|
2022-03-13 22:52:32 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setFont(GLboolean font)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderFont != -1)
|
|
|
|
GL_CHECK_ERROR(glUniform1i(mShaderFont, font ? 1 : 0));
|
|
|
|
}
|
2022-03-12 16:57:59 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::setPostProcessing(GLboolean postProcessing)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (mShaderPostProcessing != -1)
|
|
|
|
GL_CHECK_ERROR(glUniform1i(mShaderPostProcessing, postProcessing ? 1 : 0));
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::activateShaders()
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
// Install the shader program.
|
|
|
|
GL_CHECK_ERROR(glUseProgram(mProgramID));
|
|
|
|
}
|
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::deactivateShaders()
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
// Remove the shader program.
|
|
|
|
GL_CHECK_ERROR(glUseProgram(0));
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::printProgramInfoLog(GLuint programID)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (glIsProgram(programID)) {
|
|
|
|
int logLength;
|
|
|
|
int maxLength;
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &maxLength);
|
|
|
|
std::vector<char> infoLog(maxLength);
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
glGetProgramInfoLog(programID, maxLength, &logLength, &infoLog.front());
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
if (logLength > 0) {
|
|
|
|
LOG(LogDebug) << "Renderer_GL21::printProgramInfoLog():\n"
|
|
|
|
<< std::string(infoLog.begin(), infoLog.end());
|
2020-08-30 20:19:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-03-14 18:51:48 +00:00
|
|
|
else {
|
|
|
|
LOG(LogError) << "OpenGL error: " << programID << " is not a program.";
|
|
|
|
}
|
|
|
|
}
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 19:14:18 +00:00
|
|
|
void ShaderOpenGL::printShaderInfoLog(GLuint shaderID, GLenum shaderType, bool error)
|
2022-03-14 18:51:48 +00:00
|
|
|
{
|
|
|
|
if (glIsShader(shaderID)) {
|
|
|
|
int logLength;
|
|
|
|
int maxLength;
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &maxLength);
|
|
|
|
std::vector<char> infoLog(maxLength);
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
if (infoLog.size() == 0)
|
|
|
|
return;
|
2022-03-13 22:52:32 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front());
|
2020-08-30 20:19:37 +00:00
|
|
|
|
2022-03-14 18:51:48 +00:00
|
|
|
if (logLength > 0) {
|
|
|
|
LOG(LogDebug) << "Shader_GL21::printShaderInfoLog(): " << (error ? "Error" : "Warning")
|
|
|
|
<< " in "
|
|
|
|
<< (shaderType == GL_VERTEX_SHADER ? "VERTEX section:\n" :
|
|
|
|
"FRAGMENT section:\n")
|
|
|
|
<< std::string(infoLog.begin(), infoLog.end());
|
2020-08-30 20:19:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-03-14 18:51:48 +00:00
|
|
|
else {
|
|
|
|
LOG(LogError) << "OpenGL error: " << shaderID << " is not a shader.";
|
|
|
|
}
|
|
|
|
}
|