mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 14:15:38 +00:00
Updated the GLSL shader logic and added a postprocessing function.
This commit is contained in:
parent
9da16dd00e
commit
fd10aba815
|
@ -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()) {
|
||||
LOG(LogError) << "Could not create shader program.";
|
||||
return false;
|
||||
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(loadShader);
|
||||
}
|
||||
|
||||
sShaderProgramVector.push_back(desaturateShader);
|
||||
#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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
// If saturation is set below the maximum (default) value, run the desaturation shader.
|
||||
if (_vertices->saturation < 1.0) {
|
||||
Shader* desaturateShader = getShaderProgram(Shader::Desaturate);
|
||||
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->setSaturation(_vertices->saturation);
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, _numVertices));
|
||||
runShader->deactivateShaders();
|
||||
}
|
||||
}
|
||||
|
||||
// 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_TRIANGLE_STRIP, 0, _numVertices));
|
||||
desaturateShader->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
|
||||
|
|
|
@ -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],
|
||||
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]));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
|
@ -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
|
||||
|
|
137
resources/shaders/glsl/blur_horizontal.glsl
Normal file
137
resources/shaders/glsl/blur_horizontal.glsl
Normal 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
|
137
resources/shaders/glsl/blur_vertical.glsl
Normal file
137
resources/shaders/glsl/blur_vertical.glsl
Normal 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
|
|
@ -2,34 +2,30 @@
|
|||
// 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;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vTexCoord = gl_MultiTexCoord0.xy;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
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)));
|
||||
|
||||
|
|
208
resources/shaders/glsl/scanlines.glsl
Normal file
208
resources/shaders/glsl/scanlines.glsl
Normal 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
|
Loading…
Reference in a new issue