From 02ea2f89116c1de9594e95c90a4501da5772ce83 Mon Sep 17 00:00:00 2001 From: KojoZero Date: Sun, 3 May 2026 23:36:40 -0700 Subject: [PATCH] opengl implemented area sampling --- src/video_core/host_shaders/CMakeLists.txt | 2 + .../antialiasing/opengl_smaa_pass2_post.frag | 12 +- .../antialiasing/opengl_smaa_pass2_pre.frag | 1 + .../scaling/opengl_area_sampling.frag | 94 +++ .../scaling/opengl_area_sampling.vert | 11 + .../renderer_opengl/renderer_opengl.cpp | 576 +++++------------- .../renderer_opengl/renderer_opengl.h | 1 + 7 files changed, 263 insertions(+), 434 deletions(-) create mode 100644 src/video_core/host_shaders/scaling/opengl_area_sampling.frag create mode 100644 src/video_core/host_shaders/scaling/opengl_area_sampling.vert diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 113eb3b9c..e2499ae4e 100644 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -27,6 +27,8 @@ set(SHADER_FILES antialiasing/opengl_smaa_pass2_pre.vert antialiasing/opengl_smaa_pass2_post.frag antialiasing/opengl_smaa_pass2_post.vert + scaling/opengl_area_sampling.frag + scaling/opengl_area_sampling.vert antialiasing/SMAA.hlsl full_screen_triangle.vert opengl_present.frag diff --git a/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_post.frag b/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_post.frag index 7f99ef685..8341214c5 100644 --- a/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_post.frag +++ b/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_post.frag @@ -1,3 +1,11 @@ -void main() { - color = SMAANeighborhoodBlendingPS(frag_tex_coord, offset, SMAA_Input, color_texture); +vec3 LinearTosRGB(vec3 c) { + return mix(c * 12.92, 1.055 * pow(c, vec3(1.0/2.4)) - 0.055, step(0.0031308, c)); +} + +void main() { + vec4 pixel = SMAANeighborhoodBlendingPS(frag_tex_coord, offset, SMAA_Input, color_texture); + if (convert_colors == 2){ + pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a); + } + color = pixel; } diff --git a/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_pre.frag b/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_pre.frag index 3a49037fb..edd0d1137 100644 --- a/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_pre.frag +++ b/src/video_core/host_shaders/antialiasing/opengl_smaa_pass2_pre.frag @@ -4,6 +4,7 @@ // Neighborhood Blending Shader (Third Pass) uniform vec4 i_resolution; +uniform int convert_colors; #define SMAA_RT_METRICS vec4(i_resolution.z, i_resolution.w, i_resolution.x, i_resolution.y) #define SMAA_GLSL_4 diff --git a/src/video_core/host_shaders/scaling/opengl_area_sampling.frag b/src/video_core/host_shaders/scaling/opengl_area_sampling.frag new file mode 100644 index 000000000..ccf9edd55 --- /dev/null +++ b/src/video_core/host_shaders/scaling/opengl_area_sampling.frag @@ -0,0 +1,94 @@ +//? #version 460 core + +layout(location = 0) in vec2 frag_tex_coord; +layout(location = 0) out vec4 color; +layout(binding = 0) uniform sampler2D color_texture; +uniform vec4 i_resolution; +uniform vec4 o_resolution; +uniform int convert_colors; + + +/***** Area Sampling *****/ + +// By Sam Belliveau and Filippo Tarpini. Public Domain license. +// Effectively a more accurate sharp bilinear filter when upscaling, +// that also works as a mathematically perfect downscale filter. +// https://entropymine.com/imageworsener/pixelmixing/ +// https://github.com/obsproject/obs-studio/pull/1715 +// https://legacy.imagemagick.org/Usage/filter/ +vec4 AreaSampling(sampler2D textureSampler, vec2 texCoords) { + // Determine the sizes of the source and target images. + vec2 source_size = i_resolution.xy; + vec2 inverted_target_size = o_resolution.zw; + + // Determine the range of the source image that the target pixel will cover. + vec2 range = source_size * inverted_target_size; + vec2 beg = (texCoords.xy * source_size) - (range * 0.5); + vec2 end = beg + range; + + // Compute the top-left and bottom-right corners of the pixel box. + ivec2 f_beg = ivec2(floor(beg)); + ivec2 f_end = ivec2(floor(end)); + + // Compute how much of the start and end pixels are covered horizontally & vertically. + float area_w = 1.0 - fract(beg.x); + float area_n = 1.0 - fract(beg.y); + float area_e = fract(end.x); + float area_s = fract(end.y); + + // Compute the areas of the corner pixels in the pixel box. + float area_nw = area_n * area_w; + float area_ne = area_n * area_e; + float area_sw = area_s * area_w; + float area_se = area_s * area_e; + + // Initialize the color accumulator. + vec4 avg_color = vec4(0.0, 0.0, 0.0, 0.0); + + // Accumulate corner pixels. + avg_color += area_nw * texelFetch(textureSampler, ivec2(f_beg.x, f_beg.y), 0); + avg_color += area_ne * texelFetch(textureSampler, ivec2(f_end.x, f_beg.y), 0); + avg_color += area_sw * texelFetch(textureSampler, ivec2(f_beg.x, f_end.y), 0); + avg_color += area_se * texelFetch(textureSampler, ivec2(f_end.x, f_end.y), 0); + + // Determine the size of the pixel box. + int x_range = int(f_end.x - f_beg.x - 0.5); + int y_range = int(f_end.y - f_beg.y - 0.5); + + // Accumulate top and bottom edge pixels. + for (int x = f_beg.x + 1; x <= f_beg.x + x_range; ++x) { + avg_color += area_n * texelFetch(textureSampler, ivec2(x, f_beg.y), 0); + avg_color += area_s * texelFetch(textureSampler, ivec2(x, f_end.y), 0); + } + + // Accumulate left and right edge pixels and all the pixels in between. + for (int y = f_beg.y + 1; y <= f_beg.y + y_range; ++y) { + avg_color += area_w * texelFetch(textureSampler, ivec2(f_beg.x, y), 0); + avg_color += area_e * texelFetch(textureSampler, ivec2(f_end.x, y), 0); + + for (int x = f_beg.x + 1; x <= f_beg.x + x_range; ++x) { + avg_color += texelFetch(textureSampler, ivec2(x, y), 0); + } + } + + // Compute the area of the pixel box that was sampled. + float area_corners = area_nw + area_ne + area_sw + area_se; + float area_edges = float(x_range) * (area_n + area_s) + float(y_range) * (area_w + area_e); + float area_center = float(x_range) * float(y_range); + + // Return the normalized average color. + return avg_color / (area_corners + area_edges + area_center); +} + +vec3 LinearTosRGB(vec3 c) { + return mix(c * 12.92, 1.055 * pow(c, vec3(1.0/2.4)) - 0.055, step(0.0031308, c)); +} + +void main() { + // vec4 pixel = texture(color_texture, frag_tex_coord); + vec4 pixel = AreaSampling(color_texture, frag_tex_coord); + if (convert_colors == 2){ + pixel = vec4(LinearTosRGB(pixel.rgb), pixel.a); + } + color = pixel; +} \ No newline at end of file diff --git a/src/video_core/host_shaders/scaling/opengl_area_sampling.vert b/src/video_core/host_shaders/scaling/opengl_area_sampling.vert new file mode 100644 index 000000000..e39e2d2d6 --- /dev/null +++ b/src/video_core/host_shaders/scaling/opengl_area_sampling.vert @@ -0,0 +1,11 @@ +//? #version 460 +layout(location = 0) in vec2 vert_position; +layout(location = 1) in vec2 vert_tex_coord; +layout(location = 0) out vec2 frag_tex_coord; +uniform mat3x2 modelview_matrix; +void main() +{ + gl_Position = vec4(mat2(modelview_matrix) * vert_position + modelview_matrix[2], 0.0, 1.0); + frag_tex_coord = vert_tex_coord; +} + diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index e69ed2a3d..1b333ce0f 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -43,7 +43,8 @@ #include "video_core/host_shaders/antialiasing/smaa_hlsl.h" #include "video_core/host_shaders/antialiasing/AreaTex.h" #include "video_core/host_shaders/antialiasing/SearchTex.h" - +#include "video_core/host_shaders/scaling/opengl_area_sampling_frag.h" +#include "video_core/host_shaders/scaling/opengl_area_sampling_vert.h" namespace OpenGL { @@ -445,6 +446,10 @@ void RendererOpenGL::ReloadShader(Settings::StereoRenderOption render_3d) { FXAA_shader_data += HostShaders::OPENGL_FXAA_FRAG; FXAA_shader.Create(HostShaders::OPENGL_FXAA_VERT, FXAA_shader_data); + std::string AREA_SAMPLING_shader_data = fragment_shader_precision_OES; + AREA_SAMPLING_shader_data += HostShaders::OPENGL_AREA_SAMPLING_FRAG; + AREA_SAMPLING_shader.Create(HostShaders::OPENGL_AREA_SAMPLING_VERT, AREA_SAMPLING_shader_data); + std::string SimplePresent_shader_data = fragment_shader_precision_OES; SimplePresent_shader_data += HostShaders::OPENGL_SIMPLE_PRESENT_FRAG; SimplePresent_shader.Create(HostShaders::OPENGL_SIMPLE_PRESENT_VERT, SimplePresent_shader_data); @@ -478,6 +483,8 @@ void RendererOpenGL::ReloadShader(Settings::StereoRenderOption render_3d) { SMAA_PASS_2_shader_vert_data += HostShaders::SMAA_HLSL; SMAA_PASS_2_shader_vert_data += HostShaders::OPENGL_SMAA_PASS2_POST_VERT; SMAA_PASS_2_shader.Create(SMAA_PASS_2_shader_vert_data, SMAA_PASS_2_shader_frag_data); + + // state.Apply(); if (render_3d == Settings::StereoRenderOption::Anaglyph || @@ -588,7 +595,8 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree textureWidth = static_cast(screen_info.texture.height * scale_factor); textureHeight = static_cast(screen_info.texture.width * scale_factor); bool isDownsampling = false; - int antialiasingMode = 0; //0 is none, 1 is FXAA, 2 is SMAA + int scalingMode = 2; //0 is Nearest Neighbor, 1 is Hardware Bilinear, 2 is High Quality Scaling (Upsampling is Gamma Corrected Bilinear, Downsampling is Gamma Corrected Area Sampling) + int antialiasingMode = 2; //0 is none, 1 is FXAA, 2 is SMAA if (orientation == Layout::DisplayOrientation::Landscape || orientation == Layout::DisplayOrientation::LandscapeFlipped) { if (textureWidth > screenWidth){ isDownsampling = true; @@ -617,6 +625,7 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree ScreenRectVertex(1.f, -1.f, 1.f, 0.f), //Right, Bottom }}; + // Vertices for Azahar's Layout std::array output_vertices; switch (orientation) { case Layout::DisplayOrientation::Landscape: @@ -659,149 +668,15 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree } const GLuint sampler = samplers[Settings::values.filter_mode.GetValue()].handle; - // glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight); - // glUniform4f(uniform_o_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight); - // glUniform1i(uniform_convert_colors, 1); - // state.texture_units[0].texture_2d = screen_info.display_texture; - // state.texture_units[0].sampler = sampler; - - - /* - TODO: --------Rewrite - General Idea: - Always rotate to landscape in a pass - Before Bilinear Scaling convert to linear in a pass - Before Presentation convert to sRGB - - The FXAA and SMAA shaders expect pass through vertices - - Implement Gamma Corrected Bilinear: - Rotate Texture and Convert to Linear - Bilinear downscale to Screen width/height and convert to srgb - Implement SMAA: - if (isDownsampling): - Rotate Texture and Convert to Linear - Bilinear downscale to Screen width/height - Run SMAA pass 1 - Run SMAA pass 2 - Run SMAA pass 3 - Convert to srgb and output - else: - Rotate Texture and Convert to Linear - Run SMAA pass 1 - Run SMAA pass 2 - Run SMAA pass 3 - Bilinear upscale to Screen width/height and convert to srgb - - Implement FXAA: - if (isDownsampling): - Rotate Texture and Convert to Linear - Bilinear downscale to Screen width/height and convert to srgb - Run FXAA pass - Output - else: - Rotate Texture - Run FXAA pass and convert to Linear - Bilinear upscale to Screen width/height and convert to srgb - */ GLuint originalReadFramebuffer = state.draw.read_framebuffer; GLuint originalDrawFramebuffer = state.draw.draw_framebuffer; int originalViewport[4] = {state.viewport.x, state.viewport.y, state.viewport.width, state.viewport.height}; + OGLTexture antialiasFBOTexture; + // ------------------------------------------------------------- - if (antialiasingMode == 1){ - if (isDownsampling){ - //Pass 1 - OGLFramebuffer textureFBO; - textureFBO.Create(); - state.draw.read_framebuffer = textureFBO.handle; - state.draw.draw_framebuffer = textureFBO.handle; - state.Apply(); - state.viewport.x = 0; - state.viewport.y = 0; - state.viewport.width = textureWidth; - state.viewport.height = textureHeight; - state.Apply(); - OGLTexture pass1FBOTexture; - pass1FBOTexture.Create(); - pass1FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, textureWidth, textureHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass1FBOTexture.handle, 0); - state.draw.shader_program = SimplePresent_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = screen_info.display_texture; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 1); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Pass 2 - state.viewport.x = 0; - state.viewport.y = 0; - state.viewport.width = screenWidth; - state.viewport.height = screenHeight; - state.Apply(); - OGLTexture pass2FBOTexture; - pass2FBOTexture.Create(); - pass2FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, screenWidth, screenHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass2FBOTexture.handle, 0); - state.draw.shader_program = SimplePresent_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass1FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 2); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Pass 3 - state.viewport.x = 0; - state.viewport.y = 0; - state.viewport.width = screenWidth; - state.viewport.height = screenHeight; - state.Apply(); - OGLTexture pass3FBOTexture; - pass3FBOTexture.Create(); - pass3FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, screenWidth, screenHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass3FBOTexture.handle, 0); - state.draw.shader_program = FXAA_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass2FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 0); - glUniform4f(uniform_i_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Output - state.draw.read_framebuffer = originalReadFramebuffer; - state.draw.draw_framebuffer = originalDrawFramebuffer; - state.Apply(); - state.viewport.x = originalViewport[0]; - state.viewport.y = originalViewport[1]; - state.viewport.width = originalViewport[2]; - state.viewport.height = originalViewport[3]; - state.Apply(); - state.draw.shader_program = Present_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass3FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 0); - glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } else { + if (antialiasingMode != 0){ + if (antialiasingMode == 1){ //Pass 1 OGLFramebuffer textureFBO; textureFBO.Create(); @@ -834,234 +709,77 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree state.viewport.width = textureWidth; state.viewport.height = textureHeight; state.Apply(); - OGLTexture pass2FBOTexture; - pass2FBOTexture.Create(); - pass2FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, textureWidth, textureHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass2FBOTexture.handle, 0); + antialiasFBOTexture.Create(); + antialiasFBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, textureWidth, textureHeight); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, antialiasFBOTexture.handle, 0); state.draw.shader_program = FXAA_shader.handle; state.Apply(); AttachUniforms(); state.texture_units[0].texture_2d = pass1FBOTexture.handle; state.texture_units[0].sampler = samplers[1].handle; glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 1); + if (scalingMode == 2){ + glUniform1i(uniform_convert_colors, 1); + } else { + glUniform1i(uniform_convert_colors, 0); + } glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight); state.Apply(); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - //Output - state.draw.read_framebuffer = originalReadFramebuffer; - state.draw.draw_framebuffer = originalDrawFramebuffer; - state.Apply(); - state.viewport.x = originalViewport[0]; - state.viewport.y = originalViewport[1]; - state.viewport.width = originalViewport[2]; - state.viewport.height = originalViewport[3]; - state.Apply(); - state.draw.shader_program = Present_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass2FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 2); - glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - } - } else if (antialiasingMode == 2){ - //Load AreaTex and SearchTex to OGLTexture Objects - OGLTexture areatex; - areatex.Create(); - OGLTexture searchtex; - searchtex.Create(); - GLuint old_tex = OpenGLState::GetCurState().texture_units[0].texture_2d; + } else if (antialiasingMode == 2){ + //Load AreaTex and SearchTex to OGLTexture Objects + OGLTexture areatex; + areatex.Create(); + OGLTexture searchtex; + searchtex.Create(); + GLuint old_tex = OpenGLState::GetCurState().texture_units[0].texture_2d; + + glBindTexture(GL_TEXTURE_2D, areatex.handle); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT, 0, GL_RG, GL_UNSIGNED_BYTE, areaTexBytes); - glBindTexture(GL_TEXTURE_2D, areatex.handle); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RG8, AREATEX_WIDTH, AREATEX_HEIGHT, 0, GL_RG, GL_UNSIGNED_BYTE, areaTexBytes); - - glBindTexture(GL_TEXTURE_2D, searchtex.handle); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 0, GL_RED, GL_UNSIGNED_BYTE, searchTexBytes); + glBindTexture(GL_TEXTURE_2D, searchtex.handle); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, SEARCHTEX_WIDTH, SEARCHTEX_HEIGHT, 0, GL_RED, GL_UNSIGNED_BYTE, searchTexBytes); - glBindTexture(GL_TEXTURE_2D, old_tex); - - // // Draw Areatex/Search Tex to screen [For Debugging only] - // state.draw.read_framebuffer = originalReadFramebuffer; - // state.draw.draw_framebuffer = originalDrawFramebuffer; - // state.Apply(); - // state.viewport.x = originalViewport[0]; - // state.viewport.y = originalViewport[1]; - // state.viewport.width = originalViewport[2]; - // state.viewport.height = originalViewport[3]; - // state.Apply(); - // state.draw.shader_program = SimplePresent_shader.handle; - // state.Apply(); - // AttachUniforms(); - // state.texture_units[0].texture_2d = searchtex.handle; - // state.texture_units[0].sampler = samplers[1].handle; - // glUniform1i(uniform_color_texture, 0); - // glUniform1i(uniform_convert_colors, 0); - // state.Apply(); - // glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - // glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Actually Start SMAA Pipeline - // /* - //Pass 1 - OGLFramebuffer textureFBO; - textureFBO.Create(); - state.draw.read_framebuffer = textureFBO.handle; - state.draw.draw_framebuffer = textureFBO.handle; - state.Apply(); - state.viewport.x = 0; - state.viewport.y = 0; - state.viewport.width = textureWidth; - state.viewport.height = textureHeight; - state.Apply(); - OGLTexture pass1FBOTexture; - pass1FBOTexture.Create(); - pass1FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, textureWidth, textureHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass1FBOTexture.handle, 0); - state.draw.shader_program = SimplePresent_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = screen_info.display_texture; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 1); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - if (isDownsampling){ - //Pass 2 + glBindTexture(GL_TEXTURE_2D, old_tex); + + //Start SMAA Pipeline + + //Pass 1 + OGLFramebuffer textureFBO; + textureFBO.Create(); + state.draw.read_framebuffer = textureFBO.handle; + state.draw.draw_framebuffer = textureFBO.handle; + state.Apply(); state.viewport.x = 0; state.viewport.y = 0; - state.viewport.width = screenWidth; - state.viewport.height = screenHeight; + state.viewport.width = textureWidth; + state.viewport.height = textureHeight; state.Apply(); - OGLTexture pass2FBOTexture; - pass2FBOTexture.Create(); - pass2FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, screenWidth, screenHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass2FBOTexture.handle, 0); + OGLTexture pass1FBOTexture; + pass1FBOTexture.Create(); + pass1FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, textureWidth, textureHeight); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass1FBOTexture.handle, 0); state.draw.shader_program = SimplePresent_shader.handle; state.Apply(); AttachUniforms(); - state.texture_units[0].texture_2d = pass1FBOTexture.handle; + state.texture_units[0].texture_2d = screen_info.display_texture; state.texture_units[0].sampler = samplers[1].handle; glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 0); + glUniform1i(uniform_convert_colors, 1); state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Pass 3 - state.viewport.x = 0; - state.viewport.y = 0; - state.viewport.width = screenWidth; - state.viewport.height = screenHeight; - state.Apply(); - OGLTexture pass3FBOTexture; - pass3FBOTexture.Create(); - pass3FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, screenWidth, screenHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass3FBOTexture.handle, 0); - state.draw.shader_program = SMAA_PASS_0_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass2FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform4f(uniform_i_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Pass 4 - state.viewport.x = 0; - state.viewport.y = 0; - state.viewport.width = screenWidth; - state.viewport.height = screenHeight; - state.Apply(); - OGLTexture pass4FBOTexture; - pass4FBOTexture.Create(); - pass4FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, screenWidth, screenHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass4FBOTexture.handle, 0); - state.draw.shader_program = SMAA_PASS_1_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass3FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - state.texture_units[1].texture_2d = areatex.handle; - state.texture_units[1].sampler = samplers[1].handle; - state.texture_units[2].texture_2d = searchtex.handle; - state.texture_units[2].sampler = samplers[1].handle; - GLuint uniform_areatex = glGetUniformLocation(state.draw.shader_program, "areaTex"); - GLuint uniform_searchtex = glGetUniformLocation(state.draw.shader_program, "searchTex"); - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_areatex, 1); - glUniform1i(uniform_searchtex, 2); - glUniform4f(uniform_i_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Pass 5 - state.viewport.x = 0; - state.viewport.y = 0; - state.viewport.width = screenWidth; - state.viewport.height = screenHeight; - state.Apply(); - OGLTexture pass5FBOTexture; - pass5FBOTexture.Create(); - pass5FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, screenWidth, screenHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass5FBOTexture.handle, 0); - state.draw.shader_program = SMAA_PASS_2_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass4FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - state.texture_units[1].texture_2d = pass2FBOTexture.handle; - state.texture_units[1].sampler = samplers[1].handle; - GLuint uniform_smaa_input = glGetUniformLocation(state.draw.shader_program, "SMAA_Input"); - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_smaa_input, 1); - glUniform4f(uniform_i_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Output - state.draw.read_framebuffer = originalReadFramebuffer; - state.draw.draw_framebuffer = originalDrawFramebuffer; - state.Apply(); - state.viewport.x = originalViewport[0]; - state.viewport.y = originalViewport[1]; - state.viewport.width = originalViewport[2]; - state.viewport.height = originalViewport[3]; - state.Apply(); - state.draw.shader_program = Present_shader.handle; - state.Apply(); - AttachUniforms(); - state.texture_units[0].texture_2d = pass5FBOTexture.handle; - state.texture_units[0].sampler = samplers[1].handle; - glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 2); - glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); - state.Apply(); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - } else { + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + //Pass 2 state.viewport.x = 0; state.viewport.y = 0; @@ -1118,10 +836,9 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree state.viewport.width = textureWidth; state.viewport.height = textureHeight; state.Apply(); - OGLTexture pass4FBOTexture; - pass4FBOTexture.Create(); - pass4FBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, textureWidth, textureHeight); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, pass4FBOTexture.handle, 0); + antialiasFBOTexture.Create(); + antialiasFBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA16F, textureWidth, textureHeight); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, antialiasFBOTexture.handle, 0); state.draw.shader_program = SMAA_PASS_2_shader.handle; state.Apply(); AttachUniforms(); @@ -1132,11 +849,63 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree GLuint uniform_smaa_input = glGetUniformLocation(state.draw.shader_program, "SMAA_Input"); glUniform1i(uniform_color_texture, 0); glUniform1i(uniform_smaa_input, 1); + if (scalingMode == 2){ + glUniform1i(uniform_convert_colors, 0); + } else { + glUniform1i(uniform_convert_colors, 2); + } glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight); state.Apply(); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - + } + if (scalingMode == 2){ + if (isDownsampling){ + //Output + state.draw.read_framebuffer = originalReadFramebuffer; + state.draw.draw_framebuffer = originalDrawFramebuffer; + state.Apply(); + state.viewport.x = originalViewport[0]; + state.viewport.y = originalViewport[1]; + state.viewport.width = originalViewport[2]; + state.viewport.height = originalViewport[3]; + state.Apply(); + state.draw.shader_program = AREA_SAMPLING_shader.handle; + state.Apply(); + AttachUniforms(); + state.texture_units[0].texture_2d = antialiasFBOTexture.handle; + state.texture_units[0].sampler = samplers[0].handle; + glUniform1i(uniform_color_texture, 0); + glUniform1i(uniform_convert_colors, 2); + glUniform4f(uniform_i_resolution, textureWidth, textureHeight, 1.0f / textureWidth, 1.0f / textureHeight); + glUniform4f(uniform_o_resolution, screenWidth, screenHeight, 1.0f / screenWidth, 1.0f / screenHeight); + glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); + state.Apply(); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } else { + //Output + state.draw.read_framebuffer = originalReadFramebuffer; + state.draw.draw_framebuffer = originalDrawFramebuffer; + state.Apply(); + state.viewport.x = originalViewport[0]; + state.viewport.y = originalViewport[1]; + state.viewport.width = originalViewport[2]; + state.viewport.height = originalViewport[3]; + state.Apply(); + state.draw.shader_program = Present_shader.handle; + state.Apply(); + AttachUniforms(); + state.texture_units[0].texture_2d = antialiasFBOTexture.handle; + state.texture_units[0].sampler = samplers[1].handle; + glUniform1i(uniform_color_texture, 0); + glUniform1i(uniform_convert_colors, 2); + glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); + state.Apply(); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + } else if (scalingMode == 1) { //Output state.draw.read_framebuffer = originalReadFramebuffer; state.draw.draw_framebuffer = originalDrawFramebuffer; @@ -1149,17 +918,36 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree state.draw.shader_program = Present_shader.handle; state.Apply(); AttachUniforms(); - state.texture_units[0].texture_2d = pass4FBOTexture.handle; + state.texture_units[0].texture_2d = antialiasFBOTexture.handle; state.texture_units[0].sampler = samplers[1].handle; glUniform1i(uniform_color_texture, 0); - glUniform1i(uniform_convert_colors, 2); + glUniform1i(uniform_convert_colors, 0); + glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); + state.Apply(); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } else { + //Output + state.draw.read_framebuffer = originalReadFramebuffer; + state.draw.draw_framebuffer = originalDrawFramebuffer; + state.Apply(); + state.viewport.x = originalViewport[0]; + state.viewport.y = originalViewport[1]; + state.viewport.width = originalViewport[2]; + state.viewport.height = originalViewport[3]; + state.Apply(); + state.draw.shader_program = Present_shader.handle; + state.Apply(); + AttachUniforms(); + state.texture_units[0].texture_2d = antialiasFBOTexture.handle; + state.texture_units[0].sampler = samplers[0].handle; + glUniform1i(uniform_color_texture, 0); + glUniform1i(uniform_convert_colors, 0); glUniformMatrix3x2fv(uniform_modelview_matrix, 1, GL_FALSE, ortho_matrix.data()); state.Apply(); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(output_vertices), output_vertices.data()); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - // */ - } else { OGLFramebuffer postFBO; postFBO.Create(); @@ -1196,8 +984,6 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree state.viewport.y = originalViewport[1]; state.viewport.width = originalViewport[2]; state.viewport.height = originalViewport[3]; - // LOG_INFO(Render_OpenGL, "Texture Width: {}, Texture Height: {}", textureWidth, textureHeight); - // LOG_INFO(Render_OpenGL, "Viewport Width: {}, Viewport Height: {}", originalViewport[2], originalViewport[3]); state.Apply(); state.draw.shader_program = Present_shader.handle; state.Apply(); @@ -1212,84 +998,10 @@ void RendererOpenGL::DrawSingleScreen(const ScreenInfo& screen_info, float scree glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - // ------------------------------------------------------------- - // // Draw to screen (No Intermediate Simple) [For Debugging] - // state.draw.read_framebuffer = originalReadFramebuffer; - // state.draw.draw_framebuffer = originalDrawFramebuffer; - // state.Apply(); - // state.viewport.x = 0; - // state.viewport.y = 0; - // state.viewport.width = textureWidth; - // state.viewport.height = textureHeight; - // state.Apply(); - // state.draw.shader_program = SimplePresent_shader.handle; - // state.Apply(); - // AttachUniforms(); - // state.texture_units[0].texture_2d = screen_info.display_texture; - // state.texture_units[0].sampler = samplers[1].handle; - // glUniform1i(uniform_color_texture, 0); - // glUniform1i(uniform_convert_colors, 2); - // state.Apply(); - // glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data()); - // glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - // ------------------------------------------------------------- - // // Two Step draw to screen [For Debugging] - // /* - // Implement Gamma Corrected Bilinear: - // Rotate Texture and Convert to Linear - // Bilinear downscale to Screen width/height and convert to srgb - // */ - // // Create and bind Framebuffer, Create Framebuffer Texture, Bind the texture to the Framebuffer - // OGLFramebuffer postFBO; - // postFBO.Create(); - // state.draw.read_framebuffer = postFBO.handle; - // state.draw.draw_framebuffer = postFBO.handle; - // state.Apply(); - // state.viewport.x = 0; - // state.viewport.y = 0; - // state.viewport.width = static_cast(textureWidth); - // state.viewport.height = static_cast(textureHeight); - // state.Apply(); - // OGLTexture postFBOTexture; - // postFBOTexture.Create(); - // postFBOTexture.Allocate(GL_TEXTURE_2D, 1, GL_RGBA8, textureWidth, textureHeight); - // glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, postFBOTexture.handle, 0); + - // // Use the simple present shader handle to draw to the texture - // state.draw.shader_program = SimplePresent_shader.handle; - // state.Apply(); - // AttachUniforms(); - // state.texture_units[0].texture_2d = screen_info.display_texture; - // state.texture_units[0].sampler = samplers[1].handle; - // glUniform1i(uniform_color_texture, 0); - // glUniform1i(uniform_convert_colors, 1); - // state.Apply(); - // glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(rotate_vertices), rotate_vertices.data()); - // glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - // // Draw to screen - // state.draw.read_framebuffer = originalReadFramebuffer; - // state.draw.draw_framebuffer = originalDrawFramebuffer; - // state.Apply(); - // state.viewport.x = originalViewport[0]; - // state.viewport.y = originalViewport[1]; - // state.viewport.width = originalViewport[2]; - // state.viewport.height = originalViewport[3]; - // state.Apply(); - // state.draw.shader_program = SimplePresent_shader.handle; - // state.Apply(); - // AttachUniforms(); - // state.texture_units[0].texture_2d = postFBOTexture.handle; - // state.texture_units[0].sampler = samplers[1].handle; - // glUniform1i(uniform_color_texture, 0); - // glUniform1i(uniform_convert_colors, 2); - // state.Apply(); - // glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(pass_through_vertices), pass_through_vertices.data()); - // glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Reset - // postFBO.Release(); state.texture_units[0].texture_2d = 0; state.texture_units[0].sampler = 0; state.Apply(); diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 7d9f7a50c..7e79d76bd 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -98,6 +98,7 @@ private: OGLProgram SMAA_PASS_0_shader; OGLProgram SMAA_PASS_1_shader; OGLProgram SMAA_PASS_2_shader; + OGLProgram AREA_SAMPLING_shader; OGLFramebuffer screenshot_framebuffer; std::array samplers;