From cf11996d0ecdfe5fe3b93a14ba5b79a87e8b50ff Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Fri, 6 Mar 2015 22:19:38 +0600 Subject: [PATCH] Implement 3 point filtering. Code ported from mupen64plus-libretro. --- GLSLCombiner.cpp | 15 +++++++++-- GLSLCombiner.h | 2 +- Shaders.h | 67 +++++++++++++++++++++++++++++------------------- Textures.cpp | 3 +-- 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/GLSLCombiner.cpp b/GLSLCombiner.cpp index 3cfc5c22..89b09549 100644 --- a/GLSLCombiner.cpp +++ b/GLSLCombiner.cpp @@ -21,6 +21,7 @@ static GLuint g_calc_mipmap_shader_object; static GLuint g_calc_noise_shader_object; static GLuint g_calc_depth_shader_object; static GLuint g_test_alpha_shader_object; +static GLuint g_readtex_shader_object; GLuint g_monochrome_image_program = 0; #ifdef GL_IMAGE_TEXTURES_SUPPORT @@ -289,6 +290,11 @@ void InitShaderCombiner() glCompileShader(g_test_alpha_shader_object); assert(checkShaderCompileStatus(g_test_alpha_shader_object)); + g_readtex_shader_object = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(g_readtex_shader_object, 1, &fragment_shader_readtex, NULL); + glCompileShader(g_readtex_shader_object); + assert(checkShaderCompileStatus(g_readtex_shader_object)); + #ifdef GL_IMAGE_TEXTURES_SUPPORT if (video().getRender().isImageTexturesSupported() && config.frameBufferEmulation.N64DepthCompare != 0) { g_calc_depth_shader_object = glCreateShader(GL_FRAGMENT_SHADER); @@ -315,6 +321,8 @@ void DestroyShaderCombiner() { g_calc_light_shader_object = 0; glDeleteShader(g_calc_mipmap_shader_object); g_calc_mipmap_shader_object = 0; + glDeleteShader(g_readtex_shader_object); + g_readtex_shader_object = 0; glDeleteShader(g_calc_noise_shader_object); g_calc_noise_shader_object = 0; glDeleteShader(g_test_alpha_shader_object); @@ -527,9 +535,9 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo #endif } else { if (usesT0()) - strFragmentShader.append(fragment_shader_readtex0color); + strFragmentShader.append(" lowp vec4 readtex0 = readTex(uTex0, vTexCoord0, uFb8Bit == 1 || uFb8Bit == 3, uFbFixedAlpha == 1 || uFbFixedAlpha == 3); \n"); if (usesT1()) - strFragmentShader.append(fragment_shader_readtex1color); + strFragmentShader.append(" lowp vec4 readtex1 = readTex(uTex1, vTexCoord1, uFb8Bit == 2 || uFb8Bit == 3, uFbFixedAlpha == 2 || uFbFixedAlpha == 3); \n"); } if (config.generalEmulation.enableHWLighting) #ifdef SHADER_PRECISION @@ -612,6 +620,7 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo glAttachShader(m_program, g_calc_light_shader_object); if (bUseLod) glAttachShader(m_program, g_calc_mipmap_shader_object); + glAttachShader(m_program, g_readtex_shader_object); glAttachShader(m_program, g_test_alpha_shader_object); if (video().getRender().isImageTexturesSupported() && config.frameBufferEmulation.N64DepthCompare != 0) glAttachShader(m_program, g_calc_depth_shader_object); @@ -657,6 +666,7 @@ void ShaderCombiner::_locateUniforms() { LocateUniform(uMaxTile) LocateUniform(uTextureDetail); LocateUniform(uTexturePersp); + LocateUniform(uTextureFilterMode); LocateUniform(uSpecialBlendMode); LocateUniform(uFogMultiplier); @@ -863,6 +873,7 @@ void ShaderCombiner::updateColors(bool _bForce) void ShaderCombiner::updateTextureInfo(bool _bForce) { _setIUniform(m_uniforms.uTexturePersp, gDP.otherMode.texturePersp, _bForce); + _setIUniform(m_uniforms.uTextureFilterMode, config.texture.forceBilinear == 0 ? gDP.otherMode.textureFilter | (gSP.objRendermode&G_OBJRM_BILERP) : 0, _bForce); _setFV2Uniform(m_uniforms.uTexScale, gSP.texture.scales, gSP.texture.scalet, _bForce); int nFB0 = 0, nFB1 = 0; TextureCache & cache = textureCache(); diff --git a/GLSLCombiner.h b/GLSLCombiner.h index 082902f1..a8ca64ed 100644 --- a/GLSLCombiner.h +++ b/GLSLCombiner.h @@ -39,7 +39,7 @@ private: uFogMode, uFogUsage, uEnableLod, uEnableAlphaTest, uEnableDepth, uEnableDepthCompare, uEnableDepthUpdate, uDepthMode, uDepthSource, uFb8Bit, uFbFixedAlpha, uRenderState, uSpecialBlendMode, - uMaxTile, uTextureDetail, uTexturePersp, + uMaxTile, uTextureDetail, uTexturePersp, uTextureFilterMode, uAlphaCompareMode, uAlphaDitherMode, uColorDitherMode, uGammaCorrectionEnabled; fUniform uFogMultiplier, uFogOffset, uK4, uK5, uPrimLod, uScreenWidth, uScreenHeight, diff --git a/Shaders.h b/Shaders.h index e33409ee..e53ed60c 100644 --- a/Shaders.h +++ b/Shaders.h @@ -185,6 +185,7 @@ static const char* fragment_shader_header_common_functions = "lowp float snoise(); \n" "mediump float calc_light(in lowp float fLights, in lowp vec3 input_color, out lowp vec3 output_color);\n" "mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1); \n" +"lowp vec4 readTex(in sampler2D tex, in mediump vec2 texCoord, in bool fb8bit, in bool fbFixedAlpha); \n" "bool depth_compare(); \n" "bool alpha_test(in lowp float alphaValue); \n" #else @@ -332,18 +333,6 @@ static const char* fragment_shader_toonify = #endif #ifdef SHADER_PRECISION -static const char* fragment_shader_readtex0color = -" lowp vec4 readtex0 = texture(uTex0, vTexCoord0); \n" -" if (uFb8Bit == 1 || uFb8Bit == 3) readtex0 = vec4(readtex0.r); \n" -" if (uFbFixedAlpha == 1 || uFbFixedAlpha == 3) readtex0.a = 0.825; \n" -; - -static const char* fragment_shader_readtex1color = -" lowp vec4 readtex1 = texture(uTex1, vTexCoord1); \n" -" if (uFb8Bit == 2 || uFb8Bit == 3) readtex1 = vec4(readtex1.r); \n" -" if (uFbFixedAlpha == 2 || uFbFixedAlpha == 3) readtex1.a = 0.825; \n" -; - #if 0 static const char* fragment_shader_blender = " switch (uSpecialBlendMode) { \n" @@ -366,7 +355,7 @@ static const char* fragment_shader_blender = " break; \n" " case 2: \n" // Bomberman2 -" color1 = uBlendColor.rgb * uFogColor.a + color1.rgb * (1.0 - uFogColor.a); \n" +" color1 = uBlendColor.rgb * uFogColor.a + color1 * (1.0 - uFogColor.a); \n" " break; \n" " } \n" ; @@ -375,23 +364,17 @@ static const char* fragment_shader_blender = static const char* fragment_shader_end = "} \n" #else -static const char* fragment_shader_readtex0color = -" vec4 readtex0 = texture(uTex0, vTexCoord0); \n" -" if (uFb8Bit == 1 || uFb8Bit == 3) readtex0 = vec4(readtex0.r); \n" -" if (uFbFixedAlpha == 1 || uFbFixedAlpha == 3) readtex0.a = 0.825; \n" -; - -static const char* fragment_shader_readtex1color = -" vec4 readtex1 = texture(uTex1, vTexCoord1); \n" -" if (uFb8Bit == 2 || uFb8Bit == 3) readtex1 = vec4(readtex1.r); \n" -" if (uFbFixedAlpha == 2 || uFbFixedAlpha == 3) readtex1.a = 0.825; \n" -; - static const char* fragment_shader_blender = -" if (uSpecialBlendMode == 1) { \n" +" switch (uSpecialBlendMode) { \n" +" case 1: \n" // Mace " color1 = color1 * alpha1 + uBlendColor.rgb * (1.0 - alpha1); \n" -" } \n" +" break; \n" +" case 2: \n" +// Bomberman2 +" color1 = uBlendColor.rgb * uFogColor.a + color1.rgb * (1.0 - uFogColor.a); \n" +" break; \n" +" } \n" ; static const char* fragment_shader_end = @@ -541,6 +524,36 @@ static const char* fragment_shader_mipmap = #endif ; +static const char* fragment_shader_readtex = +"#version 330 core \n" +"uniform lowp int uTextureFilterMode; \n" +"lowp vec4 filterNearest(in sampler2D tex, in mediump vec2 texCoord)\n" +"{ \n" +" return texture(tex, texCoord); \n" +"} \n" +// 3 point texture filtering. +// Original author: ArthurCarvalho +// GLSL implementation: twinaphex, mupen64plus-libretro project. +"#define TEX_OFFSET(off) texture2D(tex, texCoord - (off)/texSize) \n" +"lowp vec4 filter3point(in sampler2D tex, in mediump vec2 texCoord) \n" +"{ \n" +" mediump vec2 texSize = vec2(textureSize(tex,0)); \n" +" mediump vec2 offset = fract(texCoord*texSize - vec2(0.5)); \n" +" offset -= step(1.0, offset.x + offset.y); \n" +" lowp vec4 c0 = TEX_OFFSET(offset); \n" +" lowp vec4 c1 = TEX_OFFSET(vec2(offset.x - sign(offset.x), offset.y)); \n" +" lowp vec4 c2 = TEX_OFFSET(vec2(offset.x, offset.y - sign(offset.y))); \n" +" return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0); \n" +"} \n" +"lowp vec4 readTex(in sampler2D tex, in mediump vec2 texCoord, in bool fb8bit, in bool fbFixedAlpha) \n" +"{ \n" +" lowp vec4 texColor = uTextureFilterMode == 0 ? filterNearest(tex, texCoord) : filter3point(tex, texCoord); \n" +" if (fb8bit) texColor = vec4(texColor.r); \n" +" if (fbFixedAlpha) texColor.a = 0.825; \n" +" return texColor; \n" +"} \n" +; + static const char* fragment_shader_noise = "#version 330 core \n" "uniform sampler2D uTexNoise; \n" diff --git a/Textures.cpp b/Textures.cpp index e69f8c9f..d2d0f784 100644 --- a/Textures.cpp +++ b/Textures.cpp @@ -1048,8 +1048,7 @@ void TextureCache::activateTexture(u32 _t, CachedTexture *_pTexture) glBindTexture( GL_TEXTURE_2D, _pTexture->glName ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, _pTexture->max_level); - // Set filter mode. Almost always bilinear, but check anyways - if ((gDP.otherMode.textureFilter == G_TF_BILERP) || (gDP.otherMode.textureFilter == G_TF_AVERAGE) || ((gSP.objRendermode&G_OBJRM_BILERP) != 0) || (config.texture.forceBilinear)) { + if (config.texture.forceBilinear != 0) { if (_pTexture->max_level > 0) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); else