Updated the GLSL shader logic and added a postprocessing function.

This commit is contained in:
Leon Styhre 2020-09-04 18:59:19 +02:00
parent 9da16dd00e
commit fd10aba815
9 changed files with 724 additions and 107 deletions

View file

@ -70,7 +70,7 @@ namespace Renderer
LOG(LogInfo) << "Creating window...";
if (SDL_Init(SDL_INIT_VIDEO) != 0) {
LOG(LogError) << "Error initializing SDL!\n " << SDL_GetError();
LOG(LogError) << "Couldn't initialize SDL: " << SDL_GetError() << ".";
return false;
}
@ -167,17 +167,25 @@ namespace Renderer
#if defined(USE_OPENGL_21)
LOG(LogInfo) << "Loading shaders...";
Shader* desaturateShader = new Shader();
std::vector<std::string> shaderFiles;
shaderFiles.push_back(":/shaders/glsl/desaturate.glsl");
shaderFiles.push_back(":/shaders/glsl/blur_horizontal.glsl");
shaderFiles.push_back(":/shaders/glsl/blur_vertical.glsl");
shaderFiles.push_back(":/shaders/glsl/scanlines.glsl");
desaturateShader->loadShaderFile(":/shaders/glsl/desaturate.glsl", GL_VERTEX_SHADER);
desaturateShader->loadShaderFile(":/shaders/glsl/desaturate.glsl", GL_FRAGMENT_SHADER);
for (auto it = shaderFiles.cbegin(); it != shaderFiles.cend(); it++) {
Shader* loadShader = new Shader();
if (!desaturateShader->createProgram()) {
loadShader->loadShaderFile(*it, GL_VERTEX_SHADER);
loadShader->loadShaderFile(*it, GL_FRAGMENT_SHADER);
if (!loadShader->createProgram()) {
LOG(LogError) << "Could not create shader program.";
return false;
}
sShaderProgramVector.push_back(desaturateShader);
sShaderProgramVector.push_back(loadShader);
}
#endif
return true;
@ -373,10 +381,19 @@ namespace Renderer
return red << 24 | green << 16 | blue << 8 | alpha;
}
Shader* getShaderProgram(unsigned int index)
Shader* getShaderProgram(unsigned int shaderID)
{
if (sShaderProgramVector.size() > index)
return sShaderProgramVector[index];
unsigned int index = 0;
// Find the index in sShaderProgramVector by counting the number
// of shifts required to reach 0.
while (shaderID > 0) {
shaderID = shaderID >> 1;
index++;
}
if (sShaderProgramVector.size() > index-1)
return sShaderProgramVector[index-1];
else
return nullptr;
};

View file

@ -21,7 +21,27 @@ 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;
struct shaderParameters {
std::array<GLfloat, 2> textureSize;
std::array<GLfloat, 4> textureCoordinates;
float fragmentSaturation;
unsigned int shaderPasses;
shaderParameters()
: textureSize({0.0, 0.0}),
textureCoordinates({0.0, 0.0, 0.0, 0.0}),
fragmentSaturation(1.0),
shaderPasses(1)
{};
};
static std::vector<Shader*> sShaderProgramVector;
static GLuint shaderFBO;
#if !defined(NDEBUG)
#define GL_CHECK_ERROR(Function) (Function, _GLCheckError(#Function))
@ -99,6 +119,7 @@ namespace Renderer
Vector2f tex;
unsigned int col;
float saturation = 1.0;
unsigned int shaders = 0;
};
bool init();
@ -127,7 +148,10 @@ namespace Renderer
unsigned int rgbaToABGR(unsigned int color);
unsigned int abgrToRGBA(unsigned int color);
Shader* getShaderProgram(unsigned int index);
Shader* getShaderProgram(unsigned int shaderID);
void shaderPostprocessing(unsigned int shaders,
const Renderer::shaderParameters& parameters = shaderParameters(),
unsigned char* textureRGBA = nullptr);
// API specific.
unsigned int convertColor(const unsigned int _color);
@ -161,7 +185,8 @@ namespace Renderer
const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor = Blend::SRC_ALPHA,
const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA);
const Blend::Factor _dstBlendFactor = Blend::ONE_MINUS_SRC_ALPHA,
const shaderParameters& parameters = shaderParameters());
void setProjection(const Transform4x4f& _projection);
void setMatrix(const Transform4x4f& _matrix);
void setViewport(const Rect& _viewport);

View file

@ -127,6 +127,13 @@ namespace Renderer
else {
LOG(LogInfo) << "GL_ARB_fragment_shader: OK";
}
if (extensions.find("GL_EXT_framebuffer_blit") == std::string::npos) {
LOG(LogError) << "GL_EXT_framebuffer_blit: MISSING";
missingExtension = true;
}
else {
LOG(LogInfo) << "GL_EXT_framebuffer_blit: OK";
}
if (missingExtension) {
LOG(LogError) << "Required OpenGL extensions missing.";
return false;
@ -144,11 +151,15 @@ namespace Renderer
GL_CHECK_ERROR(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
GL_CHECK_ERROR(glEnableClientState(GL_COLOR_ARRAY));
// This is the framebuffer that will be used for shader rendering.
GL_CHECK_ERROR(glGenFramebuffers(1, &shaderFBO));
return true;
}
void destroyContext()
{
GL_CHECK_ERROR(glDeleteFramebuffers(1, &shaderFBO));
SDL_GL_DeleteContext(sdlContext);
sdlContext = nullptr;
}
@ -225,28 +236,17 @@ namespace Renderer
convertBlendFactor(_dstBlendFactor)));
GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices));
// If saturation is set below the maximum (default) value, run the desaturation shader.
if (_vertices->saturation < 1.0) {
Shader* desaturateShader = getShaderProgram(Shader::Desaturate);
// Only try to use the shader if it has been loaded properly.
if (desaturateShader) {
desaturateShader->activateShaders();
desaturateShader->getVariableLocations(desaturateShader->getProgramID());
desaturateShader->setVariable(_vertices->saturation);
GL_CHECK_ERROR(glDrawArrays(GL_LINES, 0, _numVertices));
desaturateShader->deactivateShaders();
}
}
}
void drawTriangleStrips(
const Vertex* _vertices,
const unsigned int _numVertices,
const Blend::Factor _srcBlendFactor,
const Blend::Factor _dstBlendFactor)
const Blend::Factor _dstBlendFactor,
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));
@ -256,17 +256,56 @@ namespace Renderer
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) {
Shader* desaturateShader = getShaderProgram(Shader::Desaturate);
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 (desaturateShader) {
desaturateShader->activateShaders();
desaturateShader->getVariableLocations(desaturateShader->getProgramID());
desaturateShader->setVariable(_vertices->saturation);
if (runShader) {
runShader->activateShaders();
runShader->getVariableLocations(runShader->getProgramID());
runShader->setSaturation(_vertices->saturation);
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
desaturateShader->deactivateShaders();
runShader->deactivateShaders();
}
}
// Check if any other shaders are set to be used and if so, run them.
if (_vertices->shaders & SHADER_BLUR_HORIZONTAL) {
Shader* runShader = getShaderProgram(SHADER_BLUR_HORIZONTAL);
if (runShader) {
runShader->activateShaders();
runShader->getVariableLocations(runShader->getProgramID());
runShader->setTextureSize({width, height});
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
runShader->deactivateShaders();
}
}
if (_vertices->shaders & SHADER_BLUR_VERTICAL) {
Shader* runShader = getShaderProgram(SHADER_BLUR_VERTICAL);
if (runShader) {
runShader->activateShaders();
runShader->getVariableLocations(runShader->getProgramID());
runShader->setTextureSize({width, height});
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
runShader->deactivateShaders();
}
}
if (_vertices->shaders & SHADER_SCANLINES) {
Shader* runShader = getShaderProgram(SHADER_SCANLINES);
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;
if (runShader) {
runShader->activateShaders();
runShader->getVariableLocations(runShader->getProgramID());
runShader->setTextureSize({shaderWidth, shaderHeight});
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
runShader->deactivateShaders();
}
}
}
}
@ -330,6 +369,81 @@ namespace Renderer
GL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}
void shaderPostprocessing(unsigned int shaders, const Renderer::shaderParameters& parameters,
unsigned char* textureRGBA)
{
Vertex vertices[4];
GLuint width = getScreenWidth();
GLuint height = getScreenHeight();
float widthf = static_cast<float>(width);
float heightf = static_cast<float>(height);
// Set vertex positions and texture coordinates to full screen as all
// postprocessing is applied to the complete screen area.
vertices[0] = { { 0, 0 }, { 0, 1 }, 0 };
vertices[1] = { { 0, heightf }, { 0, 0 }, 0 };
vertices[2] = { { widthf, 0 }, { 1, 1 }, 0 };
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) {
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));
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shaderFBO));
// Attach the texture to the shader framebuffer.
GL_CHECK_ERROR(glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
screenTexture,
0));
// Blit the screen contents to screenTexture.
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
GL_COLOR_BUFFER_BIT, GL_NEAREST));
// Apply/render the shaders.
drawTriangleStrips(vertices, 4, 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
// typically only run every now and then to create a cached screen texture, it doesn't
// really matter.
if (textureRGBA) {
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, shaderFBO));
GL_CHECK_ERROR(glReadPixels(0, 0, width, height,
GL_RGBA, GL_UNSIGNED_BYTE, textureRGBA));
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
}
else {
// Blit the resulting postprocessed texture back to the primary framebuffer.
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, shaderFBO));
GL_CHECK_ERROR(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
GL_CHECK_ERROR(glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
GL_COLOR_BUFFER_BIT, GL_NEAREST));
}
GL_CHECK_ERROR(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
destroyTexture(screenTexture);
}
} // Renderer::
#endif // USE_OPENGL_21

View file

@ -16,12 +16,10 @@ namespace Renderer
{
Renderer::Shader::Shader()
: mProgramID(-1),
shaderFloat_0(-1),
shaderFloat_1(-1),
shaderFloat_2(-1),
shaderVec4_0(-1),
shaderVec4_1(-1),
shaderVec4_2(-1)
shaderTextureSize(-1),
shaderTextureCoord(-1),
shaderColor(-1),
shaderSaturation(-1)
{
}
@ -42,7 +40,7 @@ namespace Renderer
// Define the GLSL version (version 120 = OpenGL 2.1).
preprocessorDefines = "#version 120\n";
// Define the preprocessor macros that will let the shader compiler know whether
// 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";
@ -73,7 +71,7 @@ namespace Renderer
if (shaderCompiled != GL_TRUE) {
LOG(LogError) << "OpenGL error: Unable to compile shader " <<
currentShader << " (" << std::get<0>(*it) << ").";
printShaderInfoLog(currentShader);
printShaderInfoLog(currentShader, std::get<2>(*it));
return false;
}
@ -99,47 +97,34 @@ namespace Renderer
void Renderer::Shader::getVariableLocations(GLuint programID)
{
shaderFloat_0 = glGetUniformLocation(mProgramID, "shaderFloat_0");
shaderFloat_1 = glGetUniformLocation(mProgramID, "shaderFloat_1");
shaderFloat_2 = glGetUniformLocation(mProgramID, "shaderFloat_2");
shaderVec4_0 = glGetUniformLocation(mProgramID, "shaderVec4_0");
shaderVec4_1 = glGetUniformLocation(mProgramID, "shaderVec4_1");
shaderVec4_2 = glGetUniformLocation(mProgramID, "shaderVec4_2");
// Some of the variable names are chosen to be compatible with the RetroArch GLSL shaders.
shaderTextureSize = glGetUniformLocation(mProgramID, "TextureSize");
shaderTextureCoord = glGetAttribLocation(mProgramID, "TexCoord");
shaderColor = glGetAttribLocation(mProgramID, "COLOR");
shaderSaturation = glGetUniformLocation(mProgramID, "saturation");
}
void Renderer::Shader::setVariable(GLfloat shaderFloat, int index)
void Renderer::Shader::setTextureSize(std::array<GLfloat, 2> shaderVec2)
{
switch (index) {
case 0:
GL_CHECK_ERROR(glUniform1f(shaderFloat_0, shaderFloat));
break;
case 1:
GL_CHECK_ERROR(glUniform1f(shaderFloat_1, shaderFloat));
break;
case 2:
GL_CHECK_ERROR(glUniform1f(shaderFloat_2, shaderFloat));
break;
default:
break;
}
GL_CHECK_ERROR(glUniform2f(shaderTextureSize, shaderVec2[0], shaderVec2[1]));
}
void Renderer::Shader::setVariable(std::array<GLfloat, 4> shaderVec4, int index)
void Renderer::Shader::setTextureCoordinates(std::array<GLfloat, 4> shaderVec4)
{
switch (index) {
case 0:
GL_CHECK_ERROR(glUniform4f(shaderVec4_0, shaderVec4[0],
shaderVec4[1], shaderVec4[2], shaderVec4[3]));
break;
case 1:
GL_CHECK_ERROR(glUniform4f(shaderVec4_1, shaderVec4[0],
shaderVec4[1], shaderVec4[2], shaderVec4[3]));
case 2:
GL_CHECK_ERROR(glUniform4f(shaderVec4_2, shaderVec4[0],
shaderVec4[1], shaderVec4[2], shaderVec4[3]));
default:
break;
glEnableVertexAttribArray(shaderTextureCoord);
glVertexAttribPointer(shaderTextureCoord, 4, GL_FLOAT, GL_FALSE, 0,
(const GLvoid*)(uintptr_t)&shaderVec4);
}
void Renderer::Shader::setColor(std::array<GLfloat, 4> shaderVec4)
{
GL_CHECK_ERROR(glUniform4f(shaderColor, shaderVec4[0],
shaderVec4[1], shaderVec4[2], shaderVec4[3]));
}
void Renderer::Shader::setSaturation(GLfloat saturation)
{
GL_CHECK_ERROR(glUniform1f(shaderSaturation, saturation));
}
void Renderer::Shader::activateShaders()
@ -178,7 +163,7 @@ namespace Renderer
}
}
void Renderer::Shader::printShaderInfoLog(GLuint shaderID)
void Renderer::Shader::printShaderInfoLog(GLuint shaderID, GLenum shaderType)
{
if (glIsShader(shaderID)) {
int logLength;
@ -190,8 +175,9 @@ namespace Renderer
glGetShaderInfoLog(shaderID, maxLength, &logLength, &infoLog.front());
if (logLength > 0) {
LOG(LogDebug) << "Renderer_GL21::printShaderLog():\n" <<
std::string(infoLog.begin(), infoLog.end());
LOG(LogDebug) << "Renderer_GL21::printShaderLog(): Error in " <<
(shaderType == GL_VERTEX_SHADER ? "VERTEX section:\n" :
"FRAGMENT section:\n") << std::string(infoLog.begin(), infoLog.end());
}
}
else {

View file

@ -20,10 +20,6 @@ namespace Renderer
class Shader
{
public:
enum shaderNames {
Desaturate
};
Shader();
~Shader();
@ -36,8 +32,10 @@ namespace Renderer
// Get references to the variables inside the compiled shaders.
void getVariableLocations(GLuint programID);
// One-way communication with the compiled shaders.
void setVariable(GLfloat shaderFloat, int index = 0);
void setVariable(std::array<GLfloat, 4> shaderVec4, int index = 0);
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);
// Sets the shader program to use the loaded shaders.
void activateShaders();
// Sets the shader program to 0 which reverts to the fixed function pipeline.
@ -46,20 +44,19 @@ namespace Renderer
GLuint getProgramID();
// Only used for error logging if the shaders fail to compile or link.
void printProgramInfoLog(GLuint programID);
void printShaderInfoLog(GLuint shaderID);
void printShaderInfoLog(GLuint shaderID, GLenum shaderType);
private:
GLuint mProgramID;
std::vector<std::tuple<std::string, std::string, GLenum>> shaderVector;
// Variables used for communication with the compiled shaders.
GLint shaderFloat_0;
GLint shaderFloat_1;
GLint shaderFloat_2;
GLint shaderVec4_0;
GLint shaderVec4_1;
GLint shaderVec4_2;
GLint shaderTextureSize;
GLint shaderTextureCoord;
GLint shaderColor;
GLint shaderSaturation;
};
} // Renderer
#endif // ES_CORE_RENDERER_SHADER_GL21_H

View file

@ -0,0 +1,137 @@
// Implementation based on the article "Efficient Gaussian blur with linear sampling"
// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
/* A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX can be
found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask */
/*-----------------------------------------------------------.
/ Gaussian Blur settings /
'-----------------------------------------------------------*/
#define HW 1.00
#if defined(VERTEX)
#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif
#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;
vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
// gl_Position = MVPMatrix * VertexCoord;
COL0 = COLOR;
TEX0.xy = gl_MultiTexCoord0.xy;
// TEX0.xy = TexCoord.xy;
}
#elif defined(FRAGMENT)
#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define outsize vec4(OutputSize, 1.0 / OutputSize)
void main()
{
vec2 texcoord = vTexCoord;
// vec2 PIXEL_SIZE = SourceSize.zw;
vec2 PIXEL_SIZE = vec2(SourceSize.z, SourceSize.w);
#if __VERSION__ < 130
float sampleOffsets1 = 0.0;
float sampleOffsets2 = 1.4347826;
float sampleOffsets3 = 3.3478260;
float sampleOffsets4 = 5.2608695;
float sampleOffsets5 = 7.1739130;
float sampleWeights1 = 0.16818994;
float sampleWeights2 = 0.27276957;
float sampleWeights3 = 0.11690125;
float sampleWeights4 = 0.024067905;
float sampleWeights5 = 0.0021112196;
vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights1;
// unroll the loop
color += COMPAT_TEXTURE(Source, texcoord + vec2(sampleOffsets2* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights2;
color += COMPAT_TEXTURE(Source, texcoord - vec2(sampleOffsets2* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights2;
color += COMPAT_TEXTURE(Source, texcoord + vec2(sampleOffsets3* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights3;
color += COMPAT_TEXTURE(Source, texcoord - vec2(sampleOffsets3* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights3;
color += COMPAT_TEXTURE(Source, texcoord + vec2(sampleOffsets4* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights4;
color += COMPAT_TEXTURE(Source, texcoord - vec2(sampleOffsets4* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights4;
color += COMPAT_TEXTURE(Source, texcoord + vec2(sampleOffsets5* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights5;
color += COMPAT_TEXTURE(Source, texcoord - vec2(sampleOffsets5* HW * PIXEL_SIZE.x, 0.0)) * sampleWeights5;
#else
float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };
vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0];
for(int i = 1; i < 5; ++i) {
color += COMPAT_TEXTURE(Source, texcoord + vec2(sampleOffsets[i]*HW * PIXEL_SIZE.x, 0.0)) * sampleWeights[i];
color += COMPAT_TEXTURE(Source, texcoord - vec2(sampleOffsets[i]*HW * PIXEL_SIZE.x, 0.0)) * sampleWeights[i];
}
#endif
FragColor = vec4(color);
// FragColor = vec4(0.4, 0.0, 0.2, 0.6);
}
#endif

View file

@ -0,0 +1,137 @@
// Implementation based on the article "Efficient Gaussian blur with linear sampling"
// http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
/* A version for MasterEffect Reborn, a standalone version, and a custom shader version for SweetFX can be
found at http://reshade.me/forum/shader-presentation/27-gaussian-blur-bloom-unsharpmask */
/*-----------------------------------------------------------.
/ Gaussian Blur settings /
'-----------------------------------------------------------*/
#define VW 1.00
#if defined(VERTEX)
#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif
#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;
// out variables go here as COMPAT_VARYING whatever
vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
// gl_Position = MVPMatrix * VertexCoord;
COL0 = COLOR;
TEX0.xy = gl_MultiTexCoord0.xy;
// TEX0.xy = TexCoord.xy;
}
#elif defined(FRAGMENT)
#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define outsize vec4(OutputSize, 1.0 / OutputSize)
void main()
{
vec2 texcoord = vTexCoord;
// vec2 PIXEL_SIZE = SourceSize.zw;
vec2 PIXEL_SIZE = vec2(SourceSize.z, SourceSize.w);
#if __VERSION__ < 130
float sampleOffsets1 = 0.0;
float sampleOffsets2 = 1.4347826;
float sampleOffsets3 = 3.3478260;
float sampleOffsets4 = 5.2608695;
float sampleOffsets5 = 7.1739130;
float sampleWeights1 = 0.16818994;
float sampleWeights2 = 0.27276957;
float sampleWeights3 = 0.11690125;
float sampleWeights4 = 0.024067905;
float sampleWeights5 = 0.0021112196;
vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights1;
// unroll the loop
color += COMPAT_TEXTURE(Source, texcoord + vec2(0.0, sampleOffsets2* VW * PIXEL_SIZE.y)) * sampleWeights2;
color += COMPAT_TEXTURE(Source, texcoord - vec2(0.0, sampleOffsets2* VW * PIXEL_SIZE.y)) * sampleWeights2;
color += COMPAT_TEXTURE(Source, texcoord + vec2(0.0, sampleOffsets3* VW * PIXEL_SIZE.y)) * sampleWeights3;
color += COMPAT_TEXTURE(Source, texcoord - vec2(0.0, sampleOffsets3* VW * PIXEL_SIZE.y)) * sampleWeights3;
color += COMPAT_TEXTURE(Source, texcoord + vec2(0.0, sampleOffsets4* VW * PIXEL_SIZE.y)) * sampleWeights4;
color += COMPAT_TEXTURE(Source, texcoord - vec2(0.0, sampleOffsets4* VW * PIXEL_SIZE.y)) * sampleWeights4;
color += COMPAT_TEXTURE(Source, texcoord + vec2(0.0, sampleOffsets5* VW * PIXEL_SIZE.y)) * sampleWeights5;
color += COMPAT_TEXTURE(Source, texcoord - vec2(0.0, sampleOffsets5* VW * PIXEL_SIZE.y)) * sampleWeights5;
#else
float sampleOffsets[5] = { 0.0, 1.4347826, 3.3478260, 5.2608695, 7.1739130 };
float sampleWeights[5] = { 0.16818994, 0.27276957, 0.11690125, 0.024067905, 0.0021112196 };
vec4 color = COMPAT_TEXTURE(Source, texcoord) * sampleWeights[0];
for(int i = 1; i < 5; ++i) {
color += COMPAT_TEXTURE(Source, texcoord + vec2(0.0, sampleOffsets[i]*VW * PIXEL_SIZE.y)) * sampleWeights[i];
color += COMPAT_TEXTURE(Source, texcoord - vec2(0.0, sampleOffsets[i]*VW * PIXEL_SIZE.y)) * sampleWeights[i];
}
#endif
FragColor = vec4(color);
}
#endif

View file

@ -2,13 +2,12 @@
// desaturate.glsl
//
// Desaturates textures such as game images.
// The uniform variable 'shaderFloat_0' sets the saturation intensity.
// The uniform variable 'saturation' sets the saturation intensity.
// Setting this to the value 0 results in complete desaturation (grayscale).
//
// Vertex section of code:
// -----------------------
#if defined(VERTEX)
// Vertex section of code:
varying vec2 vTexCoord;
@ -17,19 +16,16 @@ void main(void)
vTexCoord = gl_MultiTexCoord0.xy;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#endif
#elif defined(FRAGMENT)
// Fragment section of code:
// -------------------------
#ifdef FRAGMENT
uniform float shaderFloat_0 = 1.0;
uniform float saturation = 1.0;
uniform sampler2D myTexture;
varying vec2 vTexCoord;
void main()
{
float saturation = shaderFloat_0;
vec4 color = texture2D(myTexture, vTexCoord);
vec3 grayscale = vec3(dot(color.rgb, vec3(0.2125, 0.7154, 0.0721)));

View file

@ -0,0 +1,208 @@
/*
Phosphor shader - Copyright (C) 2011 caligari.
Ported by Hyllian.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// Parameter lines go here:
// 0.5 = the spot stays inside the original pixel
// 1.0 = the spot bleeds up to the center of next pixel
#pragma parameter SPOT_WIDTH "CRTCaligari Spot Width" 0.9 0.1 1.5 0.05
#pragma parameter SPOT_HEIGHT "CRTCaligari Spot Height" 0.75 0.1 1.5 0.05
// Used to counteract the desaturation effect of weighting.
#pragma parameter COLOR_BOOST "CRTCaligari Color Boost" 1.45 1.0 2.0 0.05
// Constants used with gamma correction.
#pragma parameter InputGamma "CRTCaligari Input Gamma" 2.4 0.0 5.0 0.1
#pragma parameter OutputGamma "CRTCaligari Output Gamma" 2.2 0.0 5.0 0.1
#if defined(VERTEX)
#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying
#define COMPAT_ATTRIBUTE attribute
#define COMPAT_TEXTURE texture2D
#endif
#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec2 onex;
COMPAT_VARYING vec2 oney;
vec4 _oPosition1;
uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
// gl_Position = MVPMatrix * VertexCoord;
COL0 = COLOR;
TEX0.xy = gl_MultiTexCoord0.xy;
// TEX0.xy = TexCoord.xy;
onex = vec2(SourceSize.z, 0.0);
oney = vec2(0.0, SourceSize.w);
}
#elif defined(FRAGMENT)
#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING vec2 onex;
COMPAT_VARYING vec2 oney;
// compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutputSize vec4(OutputSize, 1.0 / OutputSize)
#ifdef PARAMETER_UNIFORM
// All parameter floats need to have COMPAT_PRECISION in front of them
uniform COMPAT_PRECISION float SPOT_WIDTH;
uniform COMPAT_PRECISION float SPOT_HEIGHT;
uniform COMPAT_PRECISION float COLOR_BOOST;
uniform COMPAT_PRECISION float InputGamma;
uniform COMPAT_PRECISION float OutputGamma;
#else
#define SPOT_WIDTH 0.9
#define SPOT_HEIGHT 0.75
#define COLOR_BOOST 1.45
#define InputGamma 2.4
#define OutputGamma 2.2
#endif
#define GAMMA_IN(color) pow(color,vec4(InputGamma))
#define GAMMA_OUT(color) pow(color, vec4(1.0 / OutputGamma))
#define TEX2D(coords) GAMMA_IN( COMPAT_TEXTURE(Source, coords) )
// Macro for weights computing
#define WEIGHT(w) \
if(w>1.0) w=1.0; \
w = 1.0 - w * w; \
w = w * w;
void main()
{
vec2 coords = ( vTexCoord * SourceSize.xy );
vec2 pixel_center = floor( coords ) + vec2(0.5, 0.5);
vec2 texture_coords = pixel_center * SourceSize.zw;
vec4 color = TEX2D( texture_coords );
float dx = coords.x - pixel_center.x;
float h_weight_00 = dx / SPOT_WIDTH;
WEIGHT( h_weight_00 );
color *= vec4( h_weight_00, h_weight_00, h_weight_00, h_weight_00 );
// get closest horizontal neighbour to blend
vec2 coords01;
if (dx>0.0) {
coords01 = onex;
dx = 1.0 - dx;
} else {
coords01 = -onex;
dx = 1.0 + dx;
}
vec4 colorNB = TEX2D( texture_coords + coords01 );
float h_weight_01 = dx / SPOT_WIDTH;
WEIGHT( h_weight_01 );
color = color + colorNB * vec4( h_weight_01 );
//////////////////////////////////////////////////////
// Vertical Blending
float dy = coords.y - pixel_center.y;
float v_weight_00 = dy / SPOT_HEIGHT;
WEIGHT( v_weight_00 );
color *= vec4( v_weight_00 );
// get closest vertical neighbour to blend
vec2 coords10;
if (dy>0.0) {
coords10 = oney;
dy = 1.0 - dy;
} else {
coords10 = -oney;
dy = 1.0 + dy;
}
colorNB = TEX2D( texture_coords + coords10 );
float v_weight_10 = dy / SPOT_HEIGHT;
WEIGHT( v_weight_10 );
color = color + colorNB * vec4( v_weight_10 * h_weight_00, v_weight_10 * h_weight_00, v_weight_10 * h_weight_00, v_weight_10 * h_weight_00 );
colorNB = TEX2D( texture_coords + coords01 + coords10 );
color = color + colorNB * vec4( v_weight_10 * h_weight_01, v_weight_10 * h_weight_01, v_weight_10 * h_weight_01, v_weight_10 * h_weight_01 );
color *= vec4( COLOR_BOOST );
FragColor = clamp( GAMMA_OUT(color), 0.0, 1.0 );
}
#endif