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:
parent
664562f988
commit
4f715b6718
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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>(),
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
Reference in New Issue