citra-emu
/
citra-canary
Archived
1
0
Fork 0

video_core: fix texture filters in GLES

anime4k: reset state.texture_units[0].texture_2d before filtering

clang-fmt
This commit is contained in:
BreadFish64 2020-04-04 16:54:49 -05:00 committed by SachinVin
parent 7b82883767
commit 91f52c2fdb
11 changed files with 88 additions and 102 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
} }

View File

@ -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;
}

View File

@ -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;

View File

@ -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));

View File

@ -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;
} }