mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 13:55:38 +00:00
138 lines
2.9 KiB
C++
138 lines
2.9 KiB
C++
|
#include "SuperAA.h"
|
||
|
#include <string>
|
||
|
|
||
|
SuperAA::SuperAA(int aaValue) :
|
||
|
m_aa(aaValue),
|
||
|
m_vao(0),
|
||
|
m_width(0),
|
||
|
m_height(0)
|
||
|
{
|
||
|
if (aaValue > 1) {
|
||
|
|
||
|
const char* vertexShader = R"glsl(
|
||
|
|
||
|
#version 410 core
|
||
|
|
||
|
// outputs
|
||
|
out vec2 fsTexCoord;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
const vec4 vertices[] = vec4[](vec4(-1.0, -1.0, 0.0, 1.0),
|
||
|
vec4(-1.0, 1.0, 0.0, 1.0),
|
||
|
vec4( 1.0, -1.0, 0.0, 1.0),
|
||
|
vec4( 1.0, 1.0, 0.0, 1.0));
|
||
|
|
||
|
fsTexCoord = (vertices[gl_VertexID % 4].xy + 1.0) / 2.0;
|
||
|
gl_Position = vertices[gl_VertexID % 4];
|
||
|
}
|
||
|
|
||
|
)glsl";
|
||
|
|
||
|
|
||
|
std::string fragmentShaderVersion = R"glsl(
|
||
|
#version 410 core
|
||
|
|
||
|
)glsl";
|
||
|
|
||
|
std::string aaString = "const int aa = ";
|
||
|
aaString += std::to_string(aaValue);
|
||
|
aaString += ";\n";
|
||
|
|
||
|
std::string fragmentShader = R"glsl(
|
||
|
|
||
|
// inputs
|
||
|
uniform sampler2D tex1; // base tex
|
||
|
in vec2 fsTexCoord;
|
||
|
|
||
|
// outputs
|
||
|
out vec4 fragColor;
|
||
|
|
||
|
vec4 GetTextureValue(sampler2D s, vec2 texCoord)
|
||
|
{
|
||
|
vec2 size = vec2(textureSize(s,0)); // want the values as floats
|
||
|
ivec2 texPos = ivec2(size * texCoord);
|
||
|
vec4 texColour = vec4(0.0);
|
||
|
|
||
|
for(int i=0; i < aa; i++) {
|
||
|
for(int j=0; j < aa; j++) {
|
||
|
texColour += texelFetch(s,ivec2(texPos.x+i,texPos.y+j),0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
texColour /= float(aa * aa);
|
||
|
|
||
|
return texColour;
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
fragColor = GetTextureValue(tex1, fsTexCoord);
|
||
|
}
|
||
|
|
||
|
)glsl";
|
||
|
|
||
|
std::string fragmentShaderString = fragmentShaderVersion + aaString + fragmentShader;
|
||
|
|
||
|
// load shaders
|
||
|
m_shader.LoadShaders(vertexShader, fragmentShaderString.c_str());
|
||
|
m_shader.GetUniformLocationMap("tex1");
|
||
|
|
||
|
// setup uniform memory
|
||
|
m_shader.EnableShader();
|
||
|
glUniform1i(m_shader.attribLocMap["tex1"], 0); // texture will be bound to unit zero
|
||
|
m_shader.DisableShader();
|
||
|
|
||
|
glGenVertexArrays(1, &m_vao);
|
||
|
glBindVertexArray(m_vao);
|
||
|
// no states needed since we do it in the shader
|
||
|
glBindVertexArray(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// need an active context bound to the current thread to destroy our objects
|
||
|
SuperAA::~SuperAA()
|
||
|
{
|
||
|
m_shader.UnloadShaders();
|
||
|
m_fbo.Destroy();
|
||
|
|
||
|
if (m_vao) {
|
||
|
glDeleteVertexArrays(1, &m_vao);
|
||
|
m_vao = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SuperAA::Init(int width, int height)
|
||
|
{
|
||
|
if (m_aa > 1) {
|
||
|
m_fbo.Destroy();
|
||
|
m_fbo.Create(width * m_aa, height * m_aa);
|
||
|
|
||
|
m_width = width;
|
||
|
m_height = height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SuperAA::Draw()
|
||
|
{
|
||
|
if (m_aa > 1) {
|
||
|
glDisable(GL_DEPTH_TEST);
|
||
|
glDisable(GL_STENCIL_TEST);
|
||
|
glDisable(GL_SCISSOR_TEST);
|
||
|
glDisable(GL_BLEND);
|
||
|
|
||
|
glBindTexture(GL_TEXTURE_2D, m_fbo.GetTextureID());
|
||
|
glBindVertexArray(m_vao);
|
||
|
glViewport(0, 0, m_width, m_height);
|
||
|
m_shader.EnableShader();
|
||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||
|
m_shader.DisableShader();
|
||
|
glBindVertexArray(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GLuint SuperAA::GetTargetID()
|
||
|
{
|
||
|
return m_fbo.GetFBOID(); // will return 0 if no render target which will be our default frame buffer (back buffer)
|
||
|
}
|