mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Updates to the OpenGL shader handling.
This commit is contained in:
parent
fcb139e567
commit
3643c08caf
|
@ -169,6 +169,7 @@ namespace Renderer
|
|||
|
||||
std::vector<std::string> shaderFiles;
|
||||
shaderFiles.push_back(":/shaders/glsl/desaturate.glsl");
|
||||
shaderFiles.push_back(":/shaders/glsl/dim.glsl");
|
||||
shaderFiles.push_back(":/shaders/glsl/blur_horizontal.glsl");
|
||||
shaderFiles.push_back(":/shaders/glsl/blur_vertical.glsl");
|
||||
shaderFiles.push_back(":/shaders/glsl/scanlines.glsl");
|
||||
|
@ -258,6 +259,8 @@ namespace Renderer
|
|||
break;
|
||||
}
|
||||
|
||||
mProjectionMatrix = projection;
|
||||
|
||||
setViewport(viewport);
|
||||
setProjection(projection);
|
||||
swapBuffers();
|
||||
|
@ -358,7 +361,8 @@ namespace Renderer
|
|||
vertices[i].pos.round();
|
||||
|
||||
bindTexture(0);
|
||||
drawTriangleStrips(vertices, 4, _srcBlendFactor, _dstBlendFactor);
|
||||
drawTriangleStrips(vertices, 4, Transform4x4f::Identity(),
|
||||
_srcBlendFactor, _dstBlendFactor);
|
||||
}
|
||||
|
||||
unsigned int rgbaToABGR(const unsigned int _color)
|
||||
|
@ -398,6 +402,11 @@ namespace Renderer
|
|||
return nullptr;
|
||||
};
|
||||
|
||||
const Transform4x4f getProjectionMatrix()
|
||||
{
|
||||
return mProjectionMatrix;
|
||||
}
|
||||
|
||||
SDL_Window* getSDLWindow() { return sdlWindow; }
|
||||
int getWindowWidth() { return windowWidth; }
|
||||
int getWindowHeight() { return windowHeight; }
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#ifndef ES_CORE_RENDERER_RENDERER_H
|
||||
#define ES_CORE_RENDERER_RENDERER_H
|
||||
|
||||
#include "math/Transform4x4f.h"
|
||||
#include "math/Vector2f.h"
|
||||
#include "Log.h"
|
||||
#include "Shader_GL21.h"
|
||||
|
@ -22,26 +23,30 @@ struct SDL_Window;
|
|||
namespace Renderer
|
||||
{
|
||||
const unsigned int SHADER_DESATURATE = 1;
|
||||
const unsigned int SHADER_BLUR_HORIZONTAL = 2;
|
||||
const unsigned int SHADER_BLUR_VERTICAL = 4;
|
||||
const unsigned int SHADER_SCANLINES = 8;
|
||||
const unsigned int SHADER_DIM = 2;
|
||||
const unsigned int SHADER_BLUR_HORIZONTAL = 4;
|
||||
const unsigned int SHADER_BLUR_VERTICAL = 8;
|
||||
const unsigned int SHADER_SCANLINES = 16;
|
||||
|
||||
struct shaderParameters {
|
||||
std::array<GLfloat, 2> textureSize;
|
||||
std::array<GLfloat, 4> textureCoordinates;
|
||||
float fragmentSaturation;
|
||||
float fragmentDimValue;
|
||||
unsigned int shaderPasses;
|
||||
|
||||
shaderParameters()
|
||||
: textureSize({0.0, 0.0}),
|
||||
textureCoordinates({0.0, 0.0, 0.0, 0.0}),
|
||||
fragmentSaturation(1.0),
|
||||
fragmentDimValue(0.4),
|
||||
shaderPasses(1)
|
||||
{};
|
||||
};
|
||||
|
||||
static std::vector<Shader*> sShaderProgramVector;
|
||||
static GLuint shaderFBO;
|
||||
static Transform4x4f mProjectionMatrix;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function))
|
||||
|
@ -149,6 +154,7 @@ namespace Renderer
|
|||
unsigned int abgrToRGBA(unsigned int color);
|
||||
|
||||
Shader* getShaderProgram(unsigned int shaderID);
|
||||
const Transform4x4f getProjectionMatrix();
|
||||
void shaderPostprocessing(unsigned int shaders,
|
||||
const Renderer::shaderParameters& parameters = shaderParameters(),
|
||||
unsigned char* textureRGBA = nullptr);
|
||||
|
@ -184,9 +190,10 @@ namespace Renderer
|
|||
void drawTriangleStrips(
|
||||
const Vertex* _vertices,
|
||||
const unsigned int _numVertices,
|
||||
const Transform4x4f& _trans = Transform4x4f::Identity(),
|
||||
const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA,
|
||||
const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA,
|
||||
const shaderParameters& parameters = shaderParameters());
|
||||
const shaderParameters& _parameters = shaderParameters());
|
||||
void setProjection(const Transform4x4f& _projection);
|
||||
void setMatrix(const Transform4x4f& _matrix);
|
||||
void setViewport(const Rect& _viewport);
|
||||
|
|
|
@ -241,12 +241,14 @@ namespace Renderer
|
|||
void drawTriangleStrips(
|
||||
const Vertex* _vertices,
|
||||
const unsigned int _numVertices,
|
||||
const Transform4x4f& _trans,
|
||||
const Blend::Factor _srcBlendFactor,
|
||||
const Blend::Factor _dstBlendFactor,
|
||||
const shaderParameters& parameters)
|
||||
const shaderParameters& _parameters)
|
||||
{
|
||||
float width = _vertices[3].pos[0];
|
||||
float height = _vertices[3].pos[1];
|
||||
|
||||
GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
|
||||
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
|
||||
GL_CHECK_ERROR(glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vertex), &_vertices[0].col));
|
||||
|
@ -254,16 +256,19 @@ namespace Renderer
|
|||
GL_CHECK_ERROR(glBlendFunc(convertBlendFactor(_srcBlendFactor),
|
||||
convertBlendFactor(_dstBlendFactor)));
|
||||
|
||||
if (_vertices[0].shaders == 0) {
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
|
||||
|
||||
for (unsigned int i = 0; i < parameters.shaderPasses; i++) {
|
||||
// If saturation is set below the maximum (default) value, run the desaturation shader.
|
||||
if (_vertices->saturation < 1.0 || parameters.fragmentSaturation < 1.0) {
|
||||
}
|
||||
else {
|
||||
for (unsigned int i = 0; i < _parameters.shaderPasses; i++) {
|
||||
// If saturation is set below the maximum (default) value, run the
|
||||
// desaturation shader.
|
||||
if (_vertices->saturation < 1.0 || _parameters.fragmentSaturation < 1.0) {
|
||||
Shader* runShader = getShaderProgram(SHADER_DESATURATE);
|
||||
// Only try to use the shader if it has been loaded properly.
|
||||
if (runShader) {
|
||||
runShader->activateShaders();
|
||||
runShader->getVariableLocations(runShader->getProgramID());
|
||||
runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans);
|
||||
runShader->setSaturation(_vertices->saturation);
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
|
||||
runShader->deactivateShaders();
|
||||
|
@ -271,11 +276,22 @@ namespace Renderer
|
|||
}
|
||||
|
||||
// Check if any other shaders are set to be used and if so, run them.
|
||||
if (_vertices->shaders & SHADER_DIM) {
|
||||
Shader* runShader = getShaderProgram(SHADER_DIM);
|
||||
if (runShader) {
|
||||
runShader->activateShaders();
|
||||
runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans);
|
||||
runShader->setDimValue(_parameters.fragmentDimValue);
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
|
||||
runShader->deactivateShaders();
|
||||
}
|
||||
}
|
||||
|
||||
if (_vertices->shaders & SHADER_BLUR_HORIZONTAL) {
|
||||
Shader* runShader = getShaderProgram(SHADER_BLUR_HORIZONTAL);
|
||||
if (runShader) {
|
||||
runShader->activateShaders();
|
||||
runShader->getVariableLocations(runShader->getProgramID());
|
||||
runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans);
|
||||
runShader->setTextureSize({width, height});
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
|
||||
runShader->deactivateShaders();
|
||||
|
@ -286,7 +302,7 @@ namespace Renderer
|
|||
Shader* runShader = getShaderProgram(SHADER_BLUR_VERTICAL);
|
||||
if (runShader) {
|
||||
runShader->activateShaders();
|
||||
runShader->getVariableLocations(runShader->getProgramID());
|
||||
runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans);
|
||||
runShader->setTextureSize({width, height});
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
|
||||
runShader->deactivateShaders();
|
||||
|
@ -298,10 +314,10 @@ namespace Renderer
|
|||
float shaderWidth = width * 1.2;
|
||||
// Workaround to get the scanlines to render somehow proportional to the
|
||||
// resolution. A better solution is for sure needed.
|
||||
float shaderHeight = height + height / ((int)height >> 7) * 1.5;
|
||||
float shaderHeight = height + height / ((int)height >> 7) * 2.0;
|
||||
if (runShader) {
|
||||
runShader->activateShaders();
|
||||
runShader->getVariableLocations(runShader->getProgramID());
|
||||
runShader->setModelViewProjectionMatrix(getProjectionMatrix() * _trans);
|
||||
runShader->setTextureSize({shaderWidth, shaderHeight});
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
|
||||
runShader->deactivateShaders();
|
||||
|
@ -309,6 +325,7 @@ namespace Renderer
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setProjection(const Transform4x4f& _projection)
|
||||
{
|
||||
|
@ -386,22 +403,11 @@ namespace Renderer
|
|||
vertices[3] = { { widthf, heightf }, { 1, 0 }, 0};
|
||||
|
||||
vertices[0].shaders = shaders;
|
||||
vertices[1].shaders = shaders;
|
||||
vertices[2].shaders = shaders;
|
||||
vertices[3].shaders = shaders;
|
||||
|
||||
if (parameters.fragmentSaturation < 1.0) {
|
||||
if (parameters.fragmentSaturation < 1.0)
|
||||
vertices[0].saturation = parameters.fragmentSaturation;
|
||||
vertices[1].saturation = parameters.fragmentSaturation;
|
||||
vertices[2].saturation = parameters.fragmentSaturation;
|
||||
vertices[3].saturation = parameters.fragmentSaturation;
|
||||
}
|
||||
|
||||
setMatrix(Transform4x4f::Identity());
|
||||
|
||||
// The following method to apply the shaders is not optimal as it requires
|
||||
// glBlitFramebuffer() to run twice. However, this function seems to be
|
||||
// very fast so maybe it's not a practical issue.
|
||||
GLuint screenTexture = createTexture(Texture::RGBA, false, false, width, height, nullptr);
|
||||
|
||||
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
|
||||
|
@ -420,7 +426,8 @@ namespace Renderer
|
|||
GL_COLOR_BUFFER_BIT, GL_NEAREST));
|
||||
|
||||
// Apply/render the shaders.
|
||||
drawTriangleStrips(vertices, 4, Blend::SRC_ALPHA, Blend::ONE_MINUS_SRC_ALPHA, parameters);
|
||||
drawTriangleStrips(vertices, 4, Transform4x4f::Identity(),
|
||||
Blend::SRC_ALPHA, Blend::ONE_MINUS_SRC_ALPHA, parameters);
|
||||
|
||||
// If textureRGBA has an address, it means that the output should go to this texture
|
||||
// rather than to the screen. The glReadPixels() function is slow, but since this would
|
||||
|
|
|
@ -198,8 +198,10 @@ namespace Renderer
|
|||
void drawTriangleStrips(
|
||||
const Vertex* _vertices,
|
||||
const unsigned int _numVertices,
|
||||
const Transform4x4f& _trans,
|
||||
const Blend::Factor _srcBlendFactor,
|
||||
const Blend::Factor _dstBlendFactor)
|
||||
const Blend::Factor _dstBlendFactor,
|
||||
const shaderParameters& _parameters)
|
||||
{
|
||||
GL_CHECK_ERROR(glVertexPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].pos));
|
||||
GL_CHECK_ERROR(glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &_vertices[0].tex));
|
||||
|
|
|
@ -16,10 +16,12 @@ namespace Renderer
|
|||
{
|
||||
Renderer::Shader::Shader()
|
||||
: mProgramID(-1),
|
||||
shaderMVPMatrix(-1),
|
||||
shaderTextureSize(-1),
|
||||
shaderTextureCoord(-1),
|
||||
shaderColor(-1),
|
||||
shaderSaturation(-1)
|
||||
shaderSaturation(-1),
|
||||
shaderDimValue(-1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -87,6 +89,7 @@ namespace Renderer
|
|||
return false;
|
||||
}
|
||||
|
||||
getVariableLocations(mProgramID);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -98,35 +101,53 @@ namespace Renderer
|
|||
void Renderer::Shader::getVariableLocations(GLuint programID)
|
||||
{
|
||||
// Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders.
|
||||
shaderMVPMatrix = glGetUniformLocation(mProgramID, "MVPMatrix");
|
||||
shaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize");
|
||||
shaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord");
|
||||
shaderColor = glGetAttribLocation(mProgramID, "COLOR");
|
||||
shaderSaturation = glGetUniformLocation(mProgramID, "saturation");
|
||||
shaderDimValue = glGetUniformLocation(mProgramID, "dimValue");
|
||||
}
|
||||
|
||||
void Renderer::Shader::setModelViewProjectionMatrix(Transform4x4f mvpMatrix)
|
||||
{
|
||||
if (shaderMVPMatrix != -1)
|
||||
GL_CHECK_ERROR(glUniformMatrix4fv(shaderMVPMatrix, 1, GL_FALSE, (GLfloat*)&mvpMatrix));
|
||||
}
|
||||
|
||||
void Renderer::Shader::setTextureSize(std::array<GLfloat, 2> shaderVec2)
|
||||
{
|
||||
if (shaderTextureSize != -1)
|
||||
GL_CHECK_ERROR(glUniform2f(shaderTextureSize, shaderVec2[0], shaderVec2[1]));
|
||||
}
|
||||
|
||||
void Renderer::Shader::setTextureCoordinates(std::array<GLfloat, 4> shaderVec4)
|
||||
{
|
||||
glEnableVertexAttribArray(shaderTextureCoord);
|
||||
glVertexAttribPointer(shaderTextureCoord, 4, GL_FLOAT, GL_FALSE, 0,
|
||||
(const GLvoid*)(uintptr_t)&shaderVec4);
|
||||
if (shaderTextureCoord != -1) {
|
||||
glVertexAttrib4f(shaderTextureCoord, shaderVec4[0], shaderVec4[1],
|
||||
shaderVec4[2], shaderVec4[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::Shader::setColor(std::array<GLfloat, 4> shaderVec4)
|
||||
{
|
||||
if (shaderColor != -1)
|
||||
GL_CHECK_ERROR(glUniform4f(shaderColor, shaderVec4[0],
|
||||
shaderVec4[1], shaderVec4[2], shaderVec4[3]));
|
||||
}
|
||||
|
||||
void Renderer::Shader::setSaturation(GLfloat saturation)
|
||||
{
|
||||
if (shaderSaturation != -1)
|
||||
GL_CHECK_ERROR(glUniform1f(shaderSaturation, saturation));
|
||||
}
|
||||
|
||||
void Renderer::Shader::setDimValue(GLfloat dimValue)
|
||||
{
|
||||
if (shaderDimValue != -1)
|
||||
GL_CHECK_ERROR(glUniform1f(shaderDimValue, dimValue));
|
||||
}
|
||||
|
||||
void Renderer::Shader::activateShaders()
|
||||
{
|
||||
GL_CHECK_ERROR(glUseProgram(mProgramID));
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
|
||||
#include "math/Transform4x4f.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include <array>
|
||||
|
@ -32,10 +34,12 @@ namespace Renderer
|
|||
// Get references to the variables inside the compiled shaders.
|
||||
void getVariableLocations(GLuint programID);
|
||||
// One-way communication with the compiled shaders.
|
||||
void setModelViewProjectionMatrix(Transform4x4f mvpMatrix);
|
||||
void setTextureSize(std::array<GLfloat, 2> shaderVec2);
|
||||
void setTextureCoordinates(std::array<GLfloat, 4> shaderVec4);
|
||||
void setColor(std::array<GLfloat, 4> shaderVec4);
|
||||
void setSaturation(GLfloat saturation);
|
||||
void setDimValue(GLfloat dimValue);
|
||||
// Sets the shader program to use the loaded shaders.
|
||||
void activateShaders();
|
||||
// Sets the shader program to 0 which reverts to the fixed function pipeline.
|
||||
|
@ -51,10 +55,12 @@ namespace Renderer
|
|||
std::vector<std::tuple<std::string, std::string, GLenum>> shaderVector;
|
||||
|
||||
// Variables used for communication with the compiled shaders.
|
||||
GLint shaderMVPMatrix;
|
||||
GLint shaderTextureSize;
|
||||
GLint shaderTextureCoord;
|
||||
GLint shaderColor;
|
||||
GLint shaderSaturation;
|
||||
GLint shaderDimValue;
|
||||
};
|
||||
|
||||
} // Renderer
|
||||
|
|
|
@ -42,7 +42,7 @@ uniform COMPAT_PRECISION vec2 InputSize;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
gl_Position = MVPMatrix * gl_Vertex;
|
||||
// gl_Position = MVPMatrix * VertexCoord;
|
||||
COL0 = COLOR;
|
||||
TEX0.xy = gl_MultiTexCoord0.xy;
|
||||
|
@ -132,6 +132,6 @@ void main()
|
|||
#endif
|
||||
|
||||
FragColor = vec4(color);
|
||||
// FragColor = vec4(0.4, 0.0, 0.2, 0.6);
|
||||
// FragColor = vec4(0.4, 0.0, 0.2, 0.2);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@ uniform COMPAT_PRECISION vec2 InputSize;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
gl_Position = MVPMatrix * gl_Vertex;
|
||||
// gl_Position = MVPMatrix * VertexCoord;
|
||||
COL0 = COLOR;
|
||||
TEX0.xy = gl_MultiTexCoord0.xy;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//
|
||||
// desaturate.glsl
|
||||
//
|
||||
// Desaturates textures such as game images.
|
||||
// Desaturates textures.
|
||||
// The uniform variable 'saturation' sets the saturation intensity.
|
||||
// Setting this to the value 0 results in complete desaturation (grayscale).
|
||||
//
|
||||
|
@ -9,12 +9,13 @@
|
|||
#if defined(VERTEX)
|
||||
// Vertex section of code:
|
||||
|
||||
uniform mat4 MVPMatrix;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vTexCoord = gl_MultiTexCoord0.xy;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
gl_Position = MVPMatrix * gl_Vertex;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
|
@ -27,9 +28,9 @@ varying vec2 vTexCoord;
|
|||
void main()
|
||||
{
|
||||
vec4 color = texture2D(myTexture, vTexCoord);
|
||||
vec3 grayscale = vec3(dot(color.rgb, vec3(0.2125, 0.7154, 0.0721)));
|
||||
|
||||
vec3 grayscale = vec3(dot(color.rgb, vec3(0.3, 0.59, 0.11)));
|
||||
vec3 blendedColor = mix(grayscale, color.rgb, saturation);
|
||||
|
||||
gl_FragColor = vec4(blendedColor, color.a);
|
||||
}
|
||||
|
||||
|
|
36
resources/shaders/glsl/dim.glsl
Normal file
36
resources/shaders/glsl/dim.glsl
Normal file
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// dim.glsl
|
||||
//
|
||||
// Dims textures.
|
||||
// The uniform variable 'dimValue' sets the amount of dimming.
|
||||
// Setting this to the value 0 results in a completely black screen.
|
||||
//
|
||||
|
||||
#if defined(VERTEX)
|
||||
// Vertex section of code:
|
||||
|
||||
uniform mat4 MVPMatrix;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vTexCoord = gl_MultiTexCoord0.xy;
|
||||
gl_Position = MVPMatrix * gl_Vertex;
|
||||
}
|
||||
|
||||
#elif defined(FRAGMENT)
|
||||
// Fragment section of code:
|
||||
|
||||
uniform float dimValue = 0.4;
|
||||
uniform sampler2D myTexture;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 dimColor = vec4(dimValue, dimValue, dimValue, 1.0);
|
||||
vec4 color = texture2D(myTexture, vTexCoord) * dimColor;
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -68,7 +68,7 @@ uniform COMPAT_PRECISION vec2 InputSize;
|
|||
|
||||
void main()
|
||||
{
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
gl_Position = MVPMatrix * gl_Vertex;
|
||||
// gl_Position = MVPMatrix * VertexCoord;
|
||||
COL0 = COLOR;
|
||||
TEX0.xy = gl_MultiTexCoord0.xy;
|
||||
|
|
Loading…
Reference in a new issue