Add nearest neighbor texture filter (#6189)

Closes https://github.com/citra-emu/citra/issues/4707
closes https://github.com/citra-emu/citra/issues/5274
This commit is contained in:
Venkat Rao 2022-11-16 11:55:14 -06:00 committed by GitHub
parent 664562f988
commit 4f715b6718
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 92 additions and 1 deletions

View file

@ -69,6 +69,8 @@ add_library(video_core STATIC
renderer_opengl/texture_filters/anime4k/anime4k_ultrafast.h
renderer_opengl/texture_filters/bicubic/bicubic.cpp
renderer_opengl/texture_filters/bicubic/bicubic.h
renderer_opengl/texture_filters/nearest_neighbor/nearest_neighbor.cpp
renderer_opengl/texture_filters/nearest_neighbor/nearest_neighbor.h
renderer_opengl/texture_filters/scale_force/scale_force.cpp
renderer_opengl/texture_filters/scale_force/scale_force.h
renderer_opengl/texture_filters/texture_filter_base.h
@ -117,6 +119,7 @@ set(SHADER_FILES
renderer_opengl/texture_filters/anime4k/x_gradient.frag
renderer_opengl/texture_filters/anime4k/y_gradient.frag
renderer_opengl/texture_filters/bicubic/bicubic.frag
renderer_opengl/texture_filters/nearest_neighbor/nearest_neighbor.frag
renderer_opengl/texture_filters/scale_force/scale_force.frag
renderer_opengl/texture_filters/tex_coord.vert
renderer_opengl/texture_filters/xbrz/xbrz_freescale.frag

View file

@ -0,0 +1,47 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "video_core/renderer_opengl/texture_filters/nearest_neighbor/nearest_neighbor.h"
#include "shaders/nearest_neighbor.frag"
#include "shaders/tex_coord.vert"
namespace OpenGL {
NearestNeighbor::NearestNeighbor(u16 scale_factor) : TextureFilterBase(scale_factor) {
program.Create(tex_coord_vert.data(), nearest_neighbor_frag.data());
vao.Create();
src_sampler.Create();
state.draw.shader_program = program.handle;
state.draw.vertex_array = vao.handle;
state.draw.shader_program = program.handle;
state.texture_units[0].sampler = src_sampler.handle;
// linear minification still makes sense
glSamplerParameteri(src_sampler.handle, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(src_sampler.handle, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(src_sampler.handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(src_sampler.handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
void NearestNeighbor::Filter(const OGLTexture& src_tex, Common::Rectangle<u32> src_rect,
const OGLTexture& dst_tex, Common::Rectangle<u32> dst_rect) {
const OpenGLState cur_state = OpenGLState::GetCurState();
state.texture_units[0].texture_2d = src_tex.handle;
state.draw.draw_framebuffer = draw_fbo.handle;
state.viewport = {static_cast<GLint>(dst_rect.left), static_cast<GLint>(dst_rect.bottom),
static_cast<GLsizei>(dst_rect.GetWidth()),
static_cast<GLsizei>(dst_rect.GetHeight())};
state.Apply();
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_tex.handle,
0);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
cur_state.Apply();
}
} // namespace OpenGL

View file

@ -0,0 +1,12 @@
//? #version 330
precision mediump float;
in vec2 tex_coord;
out vec4 frag_color;
uniform sampler2D input_texture;
void main() {
frag_color = texture(input_texture, tex_coord);
}

View file

@ -0,0 +1,27 @@
// Copyright 2022 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "video_core/renderer_opengl/gl_resource_manager.h"
#include "video_core/renderer_opengl/gl_state.h"
#include "video_core/renderer_opengl/texture_filters/texture_filter_base.h"
namespace OpenGL {
class NearestNeighbor : public TextureFilterBase {
public:
static constexpr std::string_view NAME = "Nearest Neighbor";
explicit NearestNeighbor(u16 scale_factor);
void Filter(const OGLTexture& src_tex, Common::Rectangle<u32> src_rect,
const OGLTexture& dst_tex, Common::Rectangle<u32> dst_rect) override;
private:
OpenGLState state{};
OGLProgram program{};
OGLVertexArray vao{};
OGLSampler src_sampler{};
};
} // namespace OpenGL

View file

@ -8,6 +8,7 @@
#include "common/logging/log.h"
#include "video_core/renderer_opengl/texture_filters/anime4k/anime4k_ultrafast.h"
#include "video_core/renderer_opengl/texture_filters/bicubic/bicubic.h"
#include "video_core/renderer_opengl/texture_filters/nearest_neighbor/nearest_neighbor.h"
#include "video_core/renderer_opengl/texture_filters/scale_force/scale_force.h"
#include "video_core/renderer_opengl/texture_filters/texture_filter_base.h"
#include "video_core/renderer_opengl/texture_filters/texture_filterer.h"
@ -28,6 +29,7 @@ static const std::unordered_map<std::string_view, TextureFilterContructor> filte
{TextureFilterer::NONE, [](u16) { return nullptr; }},
FilterMapPair<Anime4kUltrafast>(),
FilterMapPair<Bicubic>(),
FilterMapPair<NearestNeighbor>(),
FilterMapPair<ScaleForce>(),
FilterMapPair<XbrzFreescale>(),
};

View file

@ -14,7 +14,7 @@ namespace OpenGL {
class TextureFilterer {
public:
static constexpr std::string_view NONE = "none";
static constexpr std::string_view NONE = "Linear (Default)";
public:
explicit TextureFilterer(std::string_view filter_name, u16 scale_factor);