mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	video_core: fix texture filters in GLES
anime4k: reset state.texture_units[0].texture_2d before filtering clang-fmt
This commit is contained in:
		
							parent
							
								
									7b82883767
								
							
						
					
					
						commit
						91f52c2fdb
					
				
					 11 changed files with 88 additions and 102 deletions
				
			
		|  | @ -100,10 +100,8 @@ add_library(video_core STATIC | ||||||
| 
 | 
 | ||||||
| set(SHADER_FILES | set(SHADER_FILES | ||||||
|     renderer_opengl/texture_filters/anime4k/refine.frag |     renderer_opengl/texture_filters/anime4k/refine.frag | ||||||
|     renderer_opengl/texture_filters/anime4k/refine.vert |  | ||||||
|     renderer_opengl/texture_filters/anime4k/x_gradient.frag |     renderer_opengl/texture_filters/anime4k/x_gradient.frag | ||||||
|     renderer_opengl/texture_filters/anime4k/y_gradient.frag |     renderer_opengl/texture_filters/anime4k/y_gradient.frag | ||||||
|     renderer_opengl/texture_filters/anime4k/y_gradient.vert |  | ||||||
|     renderer_opengl/texture_filters/bicubic/bicubic.frag |     renderer_opengl/texture_filters/bicubic/bicubic.frag | ||||||
|     renderer_opengl/texture_filters/scale_force/scale_force.frag |     renderer_opengl/texture_filters/scale_force/scale_force.frag | ||||||
|     renderer_opengl/texture_filters/tex_coord.vert |     renderer_opengl/texture_filters/tex_coord.vert | ||||||
|  |  | ||||||
|  | @ -34,30 +34,14 @@ | ||||||
| #include "video_core/renderer_opengl/texture_filters/anime4k/anime4k_ultrafast.h" | #include "video_core/renderer_opengl/texture_filters/anime4k/anime4k_ultrafast.h" | ||||||
| 
 | 
 | ||||||
| #include "shaders/refine.frag" | #include "shaders/refine.frag" | ||||||
| #include "shaders/refine.vert" |  | ||||||
| #include "shaders/tex_coord.vert" | #include "shaders/tex_coord.vert" | ||||||
| #include "shaders/x_gradient.frag" | #include "shaders/x_gradient.frag" | ||||||
| #include "shaders/y_gradient.frag" | #include "shaders/y_gradient.frag" | ||||||
| #include "shaders/y_gradient.vert" |  | ||||||
| 
 | 
 | ||||||
| namespace OpenGL { | namespace OpenGL { | ||||||
| 
 | 
 | ||||||
| Anime4kUltrafast::Anime4kUltrafast(u16 scale_factor) : TextureFilterBase(scale_factor) { | Anime4kUltrafast::Anime4kUltrafast(u16 scale_factor) : TextureFilterBase(scale_factor) { | ||||||
|     const OpenGLState cur_state = OpenGLState::GetCurState(); |     const OpenGLState cur_state = OpenGLState::GetCurState(); | ||||||
|     const auto setup_temp_tex = [this](TempTex& texture, GLint internal_format, GLint format) { |  | ||||||
|         texture.fbo.Create(); |  | ||||||
|         texture.tex.Create(); |  | ||||||
|         state.draw.draw_framebuffer = texture.fbo.handle; |  | ||||||
|         state.Apply(); |  | ||||||
|         glActiveTexture(GL_TEXTURE0); |  | ||||||
|         glBindTexture(GL_TEXTURE_RECTANGLE, texture.tex.handle); |  | ||||||
|         glTexImage2D(GL_TEXTURE_RECTANGLE, 0, internal_format, 1024 * internal_scale_factor, |  | ||||||
|                      1024 * internal_scale_factor, 0, format, GL_HALF_FLOAT, nullptr); |  | ||||||
|         glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE, |  | ||||||
|                                texture.tex.handle, 0); |  | ||||||
|     }; |  | ||||||
|     setup_temp_tex(LUMAD, GL_R16F, GL_RED); |  | ||||||
|     setup_temp_tex(XY, GL_RG16F, GL_RG); |  | ||||||
| 
 | 
 | ||||||
|     vao.Create(); |     vao.Create(); | ||||||
| 
 | 
 | ||||||
|  | @ -65,17 +49,17 @@ Anime4kUltrafast::Anime4kUltrafast(u16 scale_factor) : TextureFilterBase(scale_f | ||||||
|         samplers[idx].Create(); |         samplers[idx].Create(); | ||||||
|         state.texture_units[idx].sampler = samplers[idx].handle; |         state.texture_units[idx].sampler = samplers[idx].handle; | ||||||
|         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_MIN_FILTER, |         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_MIN_FILTER, | ||||||
|                             idx == 0 ? GL_LINEAR : GL_NEAREST); |                             idx != 2 ? GL_LINEAR : GL_NEAREST); | ||||||
|         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_MAG_FILTER, |         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_MAG_FILTER, | ||||||
|                             idx == 0 ? GL_LINEAR : GL_NEAREST); |                             idx != 2 ? GL_LINEAR : GL_NEAREST); | ||||||
|         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||||||
|         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |         glSamplerParameteri(samplers[idx].handle, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||||||
|     } |     } | ||||||
|     state.draw.vertex_array = vao.handle; |     state.draw.vertex_array = vao.handle; | ||||||
| 
 | 
 | ||||||
|     gradient_x_program.Create(tex_coord_vert.data(), x_gradient_frag.data()); |     gradient_x_program.Create(tex_coord_vert.data(), x_gradient_frag.data()); | ||||||
|     gradient_y_program.Create(y_gradient_vert.data(), y_gradient_frag.data()); |     gradient_y_program.Create(tex_coord_vert.data(), y_gradient_frag.data()); | ||||||
|     refine_program.Create(refine_vert.data(), refine_frag.data()); |     refine_program.Create(tex_coord_vert.data(), refine_frag.data()); | ||||||
| 
 | 
 | ||||||
|     state.draw.shader_program = gradient_y_program.handle; |     state.draw.shader_program = gradient_y_program.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|  | @ -84,8 +68,6 @@ Anime4kUltrafast::Anime4kUltrafast(u16 scale_factor) : TextureFilterBase(scale_f | ||||||
|     state.draw.shader_program = refine_program.handle; |     state.draw.shader_program = refine_program.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
|     glUniform1i(glGetUniformLocation(refine_program.handle, "LUMAD"), 1); |     glUniform1i(glGetUniformLocation(refine_program.handle, "LUMAD"), 1); | ||||||
|     glUniform1f(glGetUniformLocation(refine_program.handle, "final_scale"), |  | ||||||
|                 static_cast<GLfloat>(internal_scale_factor) / scale_factor); |  | ||||||
| 
 | 
 | ||||||
|     cur_state.Apply(); |     cur_state.Apply(); | ||||||
| } | } | ||||||
|  | @ -95,20 +77,48 @@ void Anime4kUltrafast::Filter(GLuint src_tex, const Common::Rectangle<u32>& src_ | ||||||
|                               GLuint read_fb_handle, GLuint draw_fb_handle) { |                               GLuint read_fb_handle, GLuint draw_fb_handle) { | ||||||
|     const OpenGLState cur_state = OpenGLState::GetCurState(); |     const OpenGLState cur_state = OpenGLState::GetCurState(); | ||||||
| 
 | 
 | ||||||
|  |     // These will have handles from the previous texture that was filtered, reset them to avoid
 | ||||||
|  |     // binding invalid textures.
 | ||||||
|  |     state.texture_units[0].texture_2d = 0; | ||||||
|  |     state.texture_units[1].texture_2d = 0; | ||||||
|  |     state.texture_units[2].texture_2d = 0; | ||||||
|  | 
 | ||||||
|  |     const auto setup_temp_tex = [this, &src_rect](GLint internal_format, GLint format) { | ||||||
|  |         TempTex texture; | ||||||
|  |         texture.fbo.Create(); | ||||||
|  |         texture.tex.Create(); | ||||||
|  |         state.texture_units[0].texture_2d = texture.tex.handle; | ||||||
|  |         state.draw.draw_framebuffer = texture.fbo.handle; | ||||||
|  |         state.Apply(); | ||||||
|  |         glActiveTexture(GL_TEXTURE0); | ||||||
|  |         glBindTexture(GL_TEXTURE_2D, texture.tex.handle); | ||||||
|  |         if (GL_ARB_texture_storage) { | ||||||
|  |             glTexStorage2D(GL_TEXTURE_2D, 1, internal_format, | ||||||
|  |                            src_rect.GetWidth() * internal_scale_factor, | ||||||
|  |                            src_rect.GetHeight() * internal_scale_factor); | ||||||
|  |         } else { | ||||||
|  |             glTexImage2D( | ||||||
|  |                 GL_TEXTURE_2D, 0, internal_format, src_rect.GetWidth() * internal_scale_factor, | ||||||
|  |                 src_rect.GetHeight() * internal_scale_factor, 0, format, GL_HALF_FLOAT, nullptr); | ||||||
|  |         } | ||||||
|  |         glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, | ||||||
|  |                                texture.tex.handle, 0); | ||||||
|  |         return texture; | ||||||
|  |     }; | ||||||
|  |     auto XY = setup_temp_tex(GL_RG16F, GL_RG); | ||||||
|  |     auto LUMAD = setup_temp_tex(GL_R16F, GL_RED); | ||||||
|  | 
 | ||||||
|     state.viewport = {static_cast<GLint>(src_rect.left * internal_scale_factor), |     state.viewport = {static_cast<GLint>(src_rect.left * internal_scale_factor), | ||||||
|                       static_cast<GLint>(src_rect.bottom * internal_scale_factor), |                       static_cast<GLint>(src_rect.bottom * internal_scale_factor), | ||||||
|                       static_cast<GLsizei>(src_rect.GetWidth() * internal_scale_factor), |                       static_cast<GLsizei>(src_rect.GetWidth() * internal_scale_factor), | ||||||
|                       static_cast<GLsizei>(src_rect.GetHeight() * internal_scale_factor)}; |                       static_cast<GLsizei>(src_rect.GetHeight() * internal_scale_factor)}; | ||||||
|     state.texture_units[0].texture_2d = src_tex; |     state.texture_units[0].texture_2d = src_tex; | ||||||
|  |     state.texture_units[1].texture_2d = LUMAD.tex.handle; | ||||||
|  |     state.texture_units[2].texture_2d = XY.tex.handle; | ||||||
|     state.draw.draw_framebuffer = XY.fbo.handle; |     state.draw.draw_framebuffer = XY.fbo.handle; | ||||||
|     state.draw.shader_program = gradient_x_program.handle; |     state.draw.shader_program = gradient_x_program.handle; | ||||||
|     state.Apply(); |     state.Apply(); | ||||||
| 
 | 
 | ||||||
|     glActiveTexture(GL_TEXTURE1); |  | ||||||
|     glBindTexture(GL_TEXTURE_RECTANGLE, LUMAD.tex.handle); |  | ||||||
|     glActiveTexture(GL_TEXTURE2); |  | ||||||
|     glBindTexture(GL_TEXTURE_RECTANGLE, XY.tex.handle); |  | ||||||
| 
 |  | ||||||
|     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||||||
| 
 | 
 | ||||||
|     // gradient y pass
 |     // gradient y pass
 | ||||||
|  |  | ||||||
|  | @ -30,8 +30,6 @@ private: | ||||||
|         OGLTexture tex; |         OGLTexture tex; | ||||||
|         OGLFramebuffer fbo; |         OGLFramebuffer fbo; | ||||||
|     }; |     }; | ||||||
|     TempTex LUMAD; |  | ||||||
|     TempTex XY; |  | ||||||
| 
 | 
 | ||||||
|     std::array<OGLSampler, 3> samplers; |     std::array<OGLSampler, 3> samplers; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,14 +1,12 @@ | ||||||
| //? #version 330 | //? #version 330 | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
| in vec2 tex_coord; | in vec2 tex_coord; | ||||||
| in vec2 input_max; |  | ||||||
| 
 | 
 | ||||||
| out vec4 frag_color; | out vec4 frag_color; | ||||||
| 
 | 
 | ||||||
| uniform sampler2D HOOKED; | uniform sampler2D HOOKED; | ||||||
| uniform sampler2DRect LUMAD; | uniform sampler2D LUMAD; | ||||||
| uniform sampler2DRect LUMAG; |  | ||||||
| 
 |  | ||||||
| uniform float final_scale; |  | ||||||
| 
 | 
 | ||||||
| const float LINE_DETECT_THRESHOLD = 0.4; | const float LINE_DETECT_THRESHOLD = 0.4; | ||||||
| const float STRENGTH = 0.6; | const float STRENGTH = 0.6; | ||||||
|  | @ -21,12 +19,12 @@ struct RGBAL { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| vec4 getAverage(vec4 cc, vec4 a, vec4 b, vec4 c) { | vec4 getAverage(vec4 cc, vec4 a, vec4 b, vec4 c) { | ||||||
|     return cc * (1 - STRENGTH) + ((a + b + c) / 3) * STRENGTH; |     return cc * (1.0 - STRENGTH) + ((a + b + c) / 3.0) * STRENGTH; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define GetRGBAL(offset)                                                                           \ | #define GetRGBAL(x_offset, y_offset)                                                               \ | ||||||
|     RGBAL(textureOffset(HOOKED, tex_coord, offset),                                                \ |     RGBAL(textureLodOffset(HOOKED, tex_coord, 0.0, ivec2(x_offset, y_offset)),                     \ | ||||||
|           texture(LUMAD, clamp((gl_FragCoord.xy + offset) * final_scale, vec2(0.0), input_max)).x) |           textureLodOffset(LUMAD, tex_coord, 0.0, ivec2(x_offset, y_offset)).x) | ||||||
| 
 | 
 | ||||||
| float min3v(float a, float b, float c) { | float min3v(float a, float b, float c) { | ||||||
|     return min(min(a, b), c); |     return min(min(a, b), c); | ||||||
|  | @ -37,23 +35,23 @@ float max3v(float a, float b, float c) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| vec4 Compute() { | vec4 Compute() { | ||||||
|     RGBAL cc = GetRGBAL(ivec2(0)); |     RGBAL cc = GetRGBAL(0, 0); | ||||||
| 
 | 
 | ||||||
|     if (cc.l > LINE_DETECT_THRESHOLD) { |     if (cc.l > LINE_DETECT_THRESHOLD) { | ||||||
|         return cc.c; |         return cc.c; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     RGBAL tl = GetRGBAL(ivec2(-1, -1)); |     RGBAL tl = GetRGBAL(-1, -1); | ||||||
|     RGBAL t = GetRGBAL(ivec2(0, -1)); |     RGBAL t = GetRGBAL(0, -1); | ||||||
|     RGBAL tr = GetRGBAL(ivec2(1, -1)); |     RGBAL tr = GetRGBAL(1, -1); | ||||||
| 
 | 
 | ||||||
|     RGBAL l = GetRGBAL(ivec2(-1, 0)); |     RGBAL l = GetRGBAL(-1, 0); | ||||||
| 
 | 
 | ||||||
|     RGBAL r = GetRGBAL(ivec2(1, 0)); |     RGBAL r = GetRGBAL(1, 0); | ||||||
| 
 | 
 | ||||||
|     RGBAL bl = GetRGBAL(ivec2(-1, 1)); |     RGBAL bl = GetRGBAL(-1, 1); | ||||||
|     RGBAL b = GetRGBAL(ivec2(0, 1)); |     RGBAL b = GetRGBAL(0, 1); | ||||||
|     RGBAL br = GetRGBAL(ivec2(1, 1)); |     RGBAL br = GetRGBAL(1, 1); | ||||||
| 
 | 
 | ||||||
|     // Kernel 0 and 4 |     // Kernel 0 and 4 | ||||||
|     float maxDark = max3v(br.l, b.l, bl.l); |     float maxDark = max3v(br.l, b.l, bl.l); | ||||||
|  |  | ||||||
|  | @ -1,14 +0,0 @@ | ||||||
| //? #version 330 |  | ||||||
| out vec2 tex_coord; |  | ||||||
| out vec2 input_max; |  | ||||||
| 
 |  | ||||||
| uniform sampler2D HOOKED; |  | ||||||
| 
 |  | ||||||
| const vec2 vertices[4] = |  | ||||||
|     vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0)); |  | ||||||
| 
 |  | ||||||
| void main() { |  | ||||||
|     gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0); |  | ||||||
|     tex_coord = (vertices[gl_VertexID] + 1.0) / 2.0; |  | ||||||
|     input_max = textureSize(HOOKED, 0) * 2.0 - 1.0; |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| //? #version 330 | //? #version 330 | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
| in vec2 tex_coord; | in vec2 tex_coord; | ||||||
| 
 | 
 | ||||||
| out vec2 frag_color; | out vec2 frag_color; | ||||||
|  | @ -7,7 +9,7 @@ uniform sampler2D tex_input; | ||||||
| 
 | 
 | ||||||
| const vec3 K = vec3(0.2627, 0.6780, 0.0593); | const vec3 K = vec3(0.2627, 0.6780, 0.0593); | ||||||
| // TODO: improve handling of alpha channel | // TODO: improve handling of alpha channel | ||||||
| #define GetLum(xoffset) dot(K, textureOffset(tex_input, tex_coord, ivec2(xoffset, 0)).rgb) | #define GetLum(xoffset) dot(K, textureLodOffset(tex_input, tex_coord, 0.0, ivec2(xoffset, 0)).rgb) | ||||||
| 
 | 
 | ||||||
| void main() { | void main() { | ||||||
|     float l = GetLum(-1); |     float l = GetLum(-1); | ||||||
|  |  | ||||||
|  | @ -1,16 +1,18 @@ | ||||||
| //? #version 330 | //? #version 330 | ||||||
| in vec2 input_max; | precision mediump float; | ||||||
|  | 
 | ||||||
|  | in vec2 tex_coord; | ||||||
| 
 | 
 | ||||||
| out float frag_color; | out float frag_color; | ||||||
| 
 | 
 | ||||||
| uniform sampler2DRect tex_input; | uniform sampler2D tex_input; | ||||||
| 
 | 
 | ||||||
| void main() { | void main() { | ||||||
|     vec2 t = texture(tex_input, min(gl_FragCoord.xy + vec2(0.0, 1.0), input_max)).xy; |     vec2 t = textureLodOffset(tex_input, tex_coord, 0.0, ivec2(0, 1)).xy; | ||||||
|     vec2 c = texture(tex_input, gl_FragCoord.xy).xy; |     vec2 c = textureLod(tex_input, tex_coord, 0.0).xy; | ||||||
|     vec2 b = texture(tex_input, max(gl_FragCoord.xy - vec2(0.0, 1.0), vec2(0.0))).xy; |     vec2 b = textureLodOffset(tex_input, tex_coord, 0.0, ivec2(0, -1)).xy; | ||||||
| 
 | 
 | ||||||
|     vec2 grad = vec2(t.x + 2 * c.x + b.x, b.y - t.y); |     vec2 grad = vec2(t.x + 2.0 * c.x + b.x, b.y - t.y); | ||||||
| 
 | 
 | ||||||
|     frag_color = 1 - length(grad); |     frag_color = 1.0 - length(grad); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| //? #version 330 |  | ||||||
| out vec2 input_max; |  | ||||||
| 
 |  | ||||||
| uniform sampler2D tex_size; |  | ||||||
| 
 |  | ||||||
| const vec2 vertices[4] = |  | ||||||
|     vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0)); |  | ||||||
| 
 |  | ||||||
| void main() { |  | ||||||
|     gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0); |  | ||||||
|     input_max = textureSize(tex_size, 0) * 2 - 1; |  | ||||||
| } |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| //? #version 330 | //? #version 330 | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
| in vec2 tex_coord; | in vec2 tex_coord; | ||||||
| 
 | 
 | ||||||
| out vec4 frag_color; | out vec4 frag_color; | ||||||
|  | @ -18,7 +20,7 @@ vec4 cubic(float v) { | ||||||
| 
 | 
 | ||||||
| vec4 textureBicubic(sampler2D sampler, vec2 texCoords) { | vec4 textureBicubic(sampler2D sampler, vec2 texCoords) { | ||||||
| 
 | 
 | ||||||
|     vec2 texSize = textureSize(sampler, 0); |     vec2 texSize = vec2(textureSize(sampler, 0)); | ||||||
|     vec2 invTexSize = 1.0 / texSize; |     vec2 invTexSize = 1.0 / texSize; | ||||||
| 
 | 
 | ||||||
|     texCoords = texCoords * texSize - 0.5; |     texCoords = texCoords * texSize - 0.5; | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
| //? #version 330 | //? #version 330 | ||||||
|  | precision mediump float; | ||||||
|  | 
 | ||||||
| in vec2 tex_coord; | in vec2 tex_coord; | ||||||
| in vec2 source_size; | in vec2 source_size; | ||||||
| in vec2 output_size; | in vec2 output_size; | ||||||
|  | @ -6,7 +8,7 @@ in vec2 output_size; | ||||||
| out vec4 frag_color; | out vec4 frag_color; | ||||||
| 
 | 
 | ||||||
| uniform sampler2D tex; | uniform sampler2D tex; | ||||||
| uniform float scale; | uniform lowp float scale; | ||||||
| 
 | 
 | ||||||
| const int BLEND_NONE = 0; | const int BLEND_NONE = 0; | ||||||
| const int BLEND_NORMAL = 1; | const int BLEND_NORMAL = 1; | ||||||
|  | @ -42,12 +44,12 @@ float GetLeftRatio(vec2 center, vec2 origin, vec2 direction) { | ||||||
|     return smoothstep(-sqrt(2.0) / 2.0, sqrt(2.0) / 2.0, v); |     return smoothstep(-sqrt(2.0) / 2.0, sqrt(2.0) / 2.0, v); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| vec2 pos = fract(tex_coord * source_size) - vec2(0.5, 0.5); |  | ||||||
| vec2 coord = tex_coord - pos / source_size; |  | ||||||
| 
 |  | ||||||
| #define P(x, y) textureOffset(tex, coord, ivec2(x, y)) | #define P(x, y) textureOffset(tex, coord, ivec2(x, y)) | ||||||
| 
 | 
 | ||||||
| void main() { | void main() { | ||||||
|  |     vec2 pos = fract(tex_coord * source_size) - vec2(0.5, 0.5); | ||||||
|  |     vec2 coord = tex_coord - pos / source_size; | ||||||
|  | 
 | ||||||
|     //--------------------------------------- |     //--------------------------------------- | ||||||
|     // Input Pixel Mapping:  -|x|x|x|- |     // Input Pixel Mapping:  -|x|x|x|- | ||||||
|     //                       x|A|B|C|x |     //                       x|A|B|C|x | ||||||
|  | @ -142,15 +144,15 @@ void main() { | ||||||
|                               (IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) && |                               (IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) && | ||||||
|                                IsPixEqual(F, C) && !IsPixEqual(E, I)))); |                                IsPixEqual(F, C) && !IsPixEqual(E, I)))); | ||||||
|         vec2 origin = vec2(0.0, 1.0 / sqrt(2.0)); |         vec2 origin = vec2(0.0, 1.0 / sqrt(2.0)); | ||||||
|         ivec2 direction = ivec2(1, -1); |         vec2 direction = vec2(1.0, -1.0); | ||||||
|         if (doLineBlend) { |         if (doLineBlend) { | ||||||
|             bool haveShallowLine = |             bool haveShallowLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && E != G && D != G; |                 (STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && E != G && D != G; | ||||||
|             bool haveSteepLine = |             bool haveSteepLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && E != C && B != C; |                 (STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && E != C && B != C; | ||||||
|             origin = haveShallowLine ? vec2(0.0, 0.25) : vec2(0.0, 0.5); |             origin = haveShallowLine ? vec2(0.0, 0.25) : vec2(0.0, 0.5); | ||||||
|             direction.x += haveShallowLine ? 1 : 0; |             direction.x += haveShallowLine ? 1.0 : 0.0; | ||||||
|             direction.y -= haveSteepLine ? 1 : 0; |             direction.y -= haveSteepLine ? 1.0 : 0.0; | ||||||
|         } |         } | ||||||
|         vec4 blendPix = mix(H, F, step(ColorDist(E, F), ColorDist(E, H))); |         vec4 blendPix = mix(H, F, step(ColorDist(E, F), ColorDist(E, H))); | ||||||
|         res = mix(res, blendPix, GetLeftRatio(pos, origin, direction)); |         res = mix(res, blendPix, GetLeftRatio(pos, origin, direction)); | ||||||
|  | @ -169,15 +171,15 @@ void main() { | ||||||
|                               (IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) && |                               (IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) && | ||||||
|                                IsPixEqual(H, I) && !IsPixEqual(E, G)))); |                                IsPixEqual(H, I) && !IsPixEqual(E, G)))); | ||||||
|         vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0); |         vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0); | ||||||
|         ivec2 direction = ivec2(1, 1); |         vec2 direction = vec2(1.0, 1.0); | ||||||
|         if (doLineBlend) { |         if (doLineBlend) { | ||||||
|             bool haveShallowLine = |             bool haveShallowLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && E != A && B != A; |                 (STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && E != A && B != A; | ||||||
|             bool haveSteepLine = |             bool haveSteepLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && E != I && F != I; |                 (STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && E != I && F != I; | ||||||
|             origin = haveShallowLine ? vec2(-0.25, 0.0) : vec2(-0.5, 0.0); |             origin = haveShallowLine ? vec2(-0.25, 0.0) : vec2(-0.5, 0.0); | ||||||
|             direction.y += haveShallowLine ? 1 : 0; |             direction.y += haveShallowLine ? 1.0 : 0.0; | ||||||
|             direction.x += haveSteepLine ? 1 : 0; |             direction.x += haveSteepLine ? 1.0 : 0.0; | ||||||
|         } |         } | ||||||
|         origin = origin; |         origin = origin; | ||||||
|         direction = direction; |         direction = direction; | ||||||
|  | @ -198,15 +200,15 @@ void main() { | ||||||
|                               (IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) && |                               (IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) && | ||||||
|                                IsPixEqual(B, A) && !IsPixEqual(E, C)))); |                                IsPixEqual(B, A) && !IsPixEqual(E, C)))); | ||||||
|         vec2 origin = vec2(1.0 / sqrt(2.0), 0.0); |         vec2 origin = vec2(1.0 / sqrt(2.0), 0.0); | ||||||
|         ivec2 direction = ivec2(-1, -1); |         vec2 direction = vec2(-1.0, -1.0); | ||||||
|         if (doLineBlend) { |         if (doLineBlend) { | ||||||
|             bool haveShallowLine = |             bool haveShallowLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && E != I && H != I; |                 (STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && E != I && H != I; | ||||||
|             bool haveSteepLine = |             bool haveSteepLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && E != A && D != A; |                 (STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && E != A && D != A; | ||||||
|             origin = haveShallowLine ? vec2(0.25, 0.0) : vec2(0.5, 0.0); |             origin = haveShallowLine ? vec2(0.25, 0.0) : vec2(0.5, 0.0); | ||||||
|             direction.y -= haveShallowLine ? 1 : 0; |             direction.y -= haveShallowLine ? 1.0 : 0.0; | ||||||
|             direction.x -= haveSteepLine ? 1 : 0; |             direction.x -= haveSteepLine ? 1.0 : 0.0; | ||||||
|         } |         } | ||||||
|         vec4 blendPix = mix(F, B, step(ColorDist(E, B), ColorDist(E, F))); |         vec4 blendPix = mix(F, B, step(ColorDist(E, B), ColorDist(E, F))); | ||||||
|         res = mix(res, blendPix, GetLeftRatio(pos, origin, direction)); |         res = mix(res, blendPix, GetLeftRatio(pos, origin, direction)); | ||||||
|  | @ -225,15 +227,15 @@ void main() { | ||||||
|                               (IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) && |                               (IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) && | ||||||
|                                IsPixEqual(D, G) && !IsPixEqual(E, A)))); |                                IsPixEqual(D, G) && !IsPixEqual(E, A)))); | ||||||
|         vec2 origin = vec2(0.0, -1.0 / sqrt(2.0)); |         vec2 origin = vec2(0.0, -1.0 / sqrt(2.0)); | ||||||
|         ivec2 direction = ivec2(-1, 1); |         vec2 direction = vec2(-1.0, 1.0); | ||||||
|         if (doLineBlend) { |         if (doLineBlend) { | ||||||
|             bool haveShallowLine = |             bool haveShallowLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && E != C && F != C; |                 (STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && E != C && F != C; | ||||||
|             bool haveSteepLine = |             bool haveSteepLine = | ||||||
|                 (STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && E != G && H != G; |                 (STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && E != G && H != G; | ||||||
|             origin = haveShallowLine ? vec2(0.0, -0.25) : vec2(0.0, -0.5); |             origin = haveShallowLine ? vec2(0.0, -0.25) : vec2(0.0, -0.5); | ||||||
|             direction.x -= haveShallowLine ? 1 : 0; |             direction.x -= haveShallowLine ? 1.0 : 0.0; | ||||||
|             direction.y += haveSteepLine ? 1 : 0; |             direction.y += haveSteepLine ? 1.0 : 0.0; | ||||||
|         } |         } | ||||||
|         vec4 blendPix = mix(D, B, step(ColorDist(E, B), ColorDist(E, D))); |         vec4 blendPix = mix(D, B, step(ColorDist(E, B), ColorDist(E, D))); | ||||||
|         res = mix(res, blendPix, GetLeftRatio(pos, origin, direction)); |         res = mix(res, blendPix, GetLeftRatio(pos, origin, direction)); | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ out vec2 source_size; | ||||||
| out vec2 output_size; | out vec2 output_size; | ||||||
| 
 | 
 | ||||||
| uniform sampler2D tex; | uniform sampler2D tex; | ||||||
| uniform float scale; | uniform lowp float scale; | ||||||
| 
 | 
 | ||||||
| const vec2 vertices[4] = | const vec2 vertices[4] = | ||||||
|     vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0)); |     vec2[4](vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0)); | ||||||
|  | @ -12,6 +12,6 @@ const vec2 vertices[4] = | ||||||
| void main() { | void main() { | ||||||
|     gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0); |     gl_Position = vec4(vertices[gl_VertexID], 0.0, 1.0); | ||||||
|     tex_coord = (vertices[gl_VertexID] + 1.0) / 2.0; |     tex_coord = (vertices[gl_VertexID] + 1.0) / 2.0; | ||||||
|     source_size = textureSize(tex, 0); |     source_size = vec2(textureSize(tex, 0)); | ||||||
|     output_size = source_size * scale; |     output_size = source_size * scale; | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue