From 5ffcdb5f1eca0f208d050af0343f5cb802e684c2 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Sat, 23 Sep 2023 14:57:19 +0200 Subject: [PATCH] gl: flip Y coord when drawing framebuffer to avoid rounding issues Flip Y again when drawing to final framebuffer Fixes HUD characters truncated vertically in Test Drive V-Rally Issue #1088 --- core/rend/gl4/gldraw.cpp | 4 +--- core/rend/gl4/gles.cpp | 11 ++--------- core/rend/gles/gldraw.cpp | 22 ++++++++-------------- core/rend/gles/gles.cpp | 13 ++----------- core/rend/gles/gles.h | 3 --- core/rend/gles/postprocess.cpp | 10 +++++++--- core/rend/transform_matrix.h | 18 ++++++++---------- 7 files changed, 28 insertions(+), 53 deletions(-) diff --git a/core/rend/gl4/gldraw.cpp b/core/rend/gl4/gldraw.cpp index a76ae99f0..b3ebbbc21 100644 --- a/core/rend/gl4/gldraw.cpp +++ b/core/rend/gl4/gldraw.cpp @@ -25,7 +25,6 @@ #include static gl4PipelineShader* CurrentShader; -extern u32 gcflip; GLuint geom_fbo; GLuint stencilTexId; GLuint opaqueTexId; @@ -265,8 +264,7 @@ static void SetGPState(const PolyParam* gp) glActiveTexture(GL_TEXTURE0); } - //gcflip is global clip flip, needed for when rendering to texture due to mirrored Y direction - SetCull(gp->isp.CullMode ^ gcflip); + SetCull(gp->isp.CullMode ^ 1); //set Z mode, only if required if (Type == ListType_Punch_Through || (pass == Pass::Depth && SortingEnabled)) diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 27ce8ac2b..f92c5d855 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -791,11 +791,6 @@ bool OpenGL4Renderer::renderFrame(int width, int height) gl4ShaderUniforms.ndcMat = matrices.GetNormalMatrix(); const glm::mat4& scissor_mat = matrices.GetScissorMatrix(); ViewportMatrix = matrices.GetViewportMatrix(); - - if (!is_rtt && !config::EmulateFramebuffer) - gcflip = 0; - else - gcflip = 1; /* Handle Dc to screen scaling @@ -852,10 +847,8 @@ bool OpenGL4Renderer::renderFrame(int width, int height) #ifdef LIBRETRO if (config::EmulateFramebuffer) output_fbo = init_output_framebuffer(width, height); - else if (config::PowerVR2Filter || gl.ofbo.shiftX != 0 || gl.ofbo.shiftY != 0) - output_fbo = postProcessor.getFramebuffer(width, height); else - output_fbo = glsm_get_current_framebuffer(); + output_fbo = postProcessor.getFramebuffer(width, height); glViewport(0, 0, width, height); #else output_fbo = init_output_framebuffer(rendering_width, rendering_height); @@ -973,7 +966,7 @@ bool OpenGL4Renderer::renderFrame(int width, int height) gl4DrawStrips(output_fbo, rendering_width, rendering_height); #ifdef LIBRETRO - if ((config::PowerVR2Filter || gl.ofbo.shiftX != 0 || gl.ofbo.shiftY != 0) && !is_rtt && !config::EmulateFramebuffer) + if (!is_rtt && !config::EmulateFramebuffer) postProcessor.render(glsm_get_current_framebuffer()); #endif } diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 3553682ab..2a376bdf8 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -71,7 +71,6 @@ const u32 SrcBlendGL[] = }; PipelineShader* CurrentShader; -u32 gcflip; void SetCull(u32 CullMode) { @@ -235,8 +234,7 @@ void SetGPState(const PolyParam* gp,u32 cflip=0) //set cull mode ! //cflip is required when exploding triangles for triangle sorting - //gcflip is global clip flip, needed for when rendering to texture due to mirrored Y direction - SetCull(gp->isp.CullMode^cflip^gcflip); + SetCull(gp->isp.CullMode ^ cflip ^ 1); //set Z mode, only if required if (Type == ListType_Punch_Through || (Type == ListType_Translucent && SortingEnabled)) @@ -328,7 +326,7 @@ static void drawSorted(int first, int count, bool multipass) // FIXME no clipping in modvol shader //SetTileClip(gp->tileclip,true); - SetCull(params->isp.CullMode ^ gcflip); + SetCull(params->isp.CullMode ^ 1); glDrawElements(GL_TRIANGLES, pvrrc.sortedTriangles[p].count, gl.index_type, (GLvoid*)(gl.get_index_size() * pvrrc.sortedTriangles[p].first)); @@ -623,11 +621,8 @@ void OpenGLRenderer::RenderFramebuffer(const FramebufferInfo& info) saveCurrentFramebuffer(); getVideoShift(gl.ofbo.shiftX, gl.ofbo.shiftY); #ifdef LIBRETRO - if (config::PowerVR2Filter || gl.ofbo.shiftX != 0 || gl.ofbo.shiftY != 0) - { - glBindFramebuffer(GL_FRAMEBUFFER, postProcessor.getFramebuffer(gl.dcfb.width, gl.dcfb.height)); - glcache.BindTexture(GL_TEXTURE_2D, gl.dcfb.tex); - } + glBindFramebuffer(GL_FRAMEBUFFER, postProcessor.getFramebuffer(gl.dcfb.width, gl.dcfb.height)); + glcache.BindTexture(GL_TEXTURE_2D, gl.dcfb.tex); #else if (gl.ofbo2.framebuffer != nullptr && (gl.dcfb.width != gl.ofbo2.framebuffer->getWidth() || gl.dcfb.height != gl.ofbo2.framebuffer->getHeight())) @@ -656,11 +651,10 @@ void OpenGLRenderer::RenderFramebuffer(const FramebufferInfo& info) else { glcache.Disable(GL_BLEND); - drawQuad(gl.dcfb.tex, false, true); + drawQuad(gl.dcfb.tex, false, false); } #ifdef LIBRETRO - if (config::PowerVR2Filter || gl.ofbo.shiftX != 0 || gl.ofbo.shiftY != 0) - postProcessor.render(glsm_get_current_framebuffer()); + postProcessor.render(glsm_get_current_framebuffer()); #else renderLastFrame(); #endif @@ -789,7 +783,7 @@ bool OpenGLRenderer::renderLastFrame() vertices = sverts; } glcache.Disable(GL_BLEND); - drawQuad(framebuffer->getTexture(), config::Rotate90, false, vertices); + drawQuad(framebuffer->getTexture(), config::Rotate90, true, vertices); } else { @@ -799,7 +793,7 @@ bool OpenGLRenderer::renderLastFrame() glcache.ClearColor(VO_BORDER_COL.red(), VO_BORDER_COL.green(), VO_BORDER_COL.blue(), 1.f); glClear(GL_COLOR_BUFFER_BIT); glBlitFramebuffer(-gl.ofbo.shiftX, gl.ofbo.shiftY, framebuffer->getWidth() - gl.ofbo.shiftX, framebuffer->getHeight() + gl.ofbo.shiftY, - dx, dy, settings.display.width - dx, settings.display.height - dy, + dx, settings.display.height - dy, settings.display.width - dx, dy, GL_COLOR_BUFFER_BIT, config::TextureFiltering == 1 ? GL_NEAREST : GL_LINEAR); glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.origFbo); #endif diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index 4832facb4..710b255f3 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -1195,11 +1195,6 @@ bool OpenGLRenderer::renderFrame(int width, int height) const glm::mat4& scissor_mat = matrices.GetScissorMatrix(); ViewportMatrix = matrices.GetViewportMatrix(); - if (!is_rtt && !config::EmulateFramebuffer) - gcflip = 0; - else - gcflip = 1; - ShaderUniforms.depth_coefs[0] = 2 / (vtx_max_fZ - vtx_min_fZ); ShaderUniforms.depth_coefs[1] = -vtx_min_fZ - 1; ShaderUniforms.depth_coefs[2] = 0; @@ -1294,13 +1289,9 @@ bool OpenGLRenderer::renderFrame(int width, int height) if (init_output_framebuffer(width, height) == 0) return false; } - else if (config::PowerVR2Filter || gl.ofbo.shiftX != 0 || gl.ofbo.shiftY != 0) - { - glBindFramebuffer(GL_FRAMEBUFFER, postProcessor.getFramebuffer(width, height)); - } else { - glBindFramebuffer(GL_FRAMEBUFFER, glsm_get_current_framebuffer()); + glBindFramebuffer(GL_FRAMEBUFFER, postProcessor.getFramebuffer(width, height)); } glViewport(0, 0, width, height); #else @@ -1410,7 +1401,7 @@ bool OpenGLRenderer::renderFrame(int width, int height) DrawStrips(); #ifdef LIBRETRO - if ((config::PowerVR2Filter || gl.ofbo.shiftX != 0 || gl.ofbo.shiftY != 0) && !is_rtt && !config::EmulateFramebuffer) + if (!is_rtt && !config::EmulateFramebuffer) postProcessor.render(glsm_get_current_framebuffer()); #endif } diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 2fa99e4f2..3b256c53d 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -36,9 +36,6 @@ // Naomi2 #define VERTEX_NORM_ARRAY 7 -//vertex types -extern u32 gcflip; - extern glm::mat4 ViewportMatrix; void DrawStrips(); diff --git a/core/rend/gles/postprocess.cpp b/core/rend/gles/postprocess.cpp index 241596aed..921b28878 100644 --- a/core/rend/gles/postprocess.cpp +++ b/core/rend/gles/postprocess.cpp @@ -67,7 +67,9 @@ float dithertable[16] = float[]( void main() { vec2 texcoord = vTexCoord; + texcoord.y = 1. - texcoord.y; vec2 texcoord2 = vTexCoord; + texcoord2.y = 1. - texcoord2.y; texcoord2.x *= float(TextureSize.x); texcoord2.y *= float(TextureSize.y); vec4 color = texture(Source, texcoord); @@ -78,6 +80,7 @@ void main() int taps = int(3); float tap = (2.666f/float(taps)) / float(min(TextureSize.y, 720)); vec2 texcoord4 = vTexCoord; + texcoord4.y = 1. - texcoord4.y; texcoord4.y -= tap * 2.f; int bl; vec4 ble = vec4(0.0); @@ -136,6 +139,7 @@ void main() int taps = 32; float tap = 12.0/taps; vec2 texcoord4 = vTexCoord; + texcoord4.y = 1. - texcoord4.y; texcoord4.x = texcoord4.x + (2.0/640.0); texcoord4.y = texcoord4.y; vec4 blur1 = texture(Source, texcoord4); @@ -281,7 +285,7 @@ void PostProcessor::render(GLuint output_fbo) if (!config::PowerVR2Filter) { - // Just handle shifting + // Just handle shifting and Y flipping if (gl.gl_major < 3) { glBindFramebuffer(GL_FRAMEBUFFER, output_fbo); @@ -301,7 +305,7 @@ void PostProcessor::render(GLuint output_fbo) vertices[1] = vertices[11] = 1.f - gl.ofbo.shiftY * 2.f / framebuffer->getHeight(); vertices[6] = vertices[16] = vertices[1] - 2; glcache.Disable(GL_BLEND); - drawQuad(framebuffer->getTexture(), false, false, vertices); + drawQuad(framebuffer->getTexture(), false, true, vertices); } else { @@ -311,7 +315,7 @@ void PostProcessor::render(GLuint output_fbo) glcache.ClearColor(VO_BORDER_COL.red(), VO_BORDER_COL.green(), VO_BORDER_COL.blue(), 1.f); glClear(GL_COLOR_BUFFER_BIT); glBlitFramebuffer(-gl.ofbo.shiftX, gl.ofbo.shiftY, framebuffer->getWidth() - gl.ofbo.shiftX, framebuffer->getHeight() + gl.ofbo.shiftY, - 0, 0, framebuffer->getWidth(), framebuffer->getHeight(), + 0, framebuffer->getHeight(), framebuffer->getWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_FRAMEBUFFER, output_fbo); #endif diff --git a/core/rend/transform_matrix.h b/core/rend/transform_matrix.h index f3291354d..271ea3a43 100644 --- a/core/rend/transform_matrix.h +++ b/core/rend/transform_matrix.h @@ -101,9 +101,7 @@ class TransformMatrix void CalcMatrices(const rend_context *renderingContext, int width = 0, int height = 0) { - const int screenFlipY = (System == COORD_OPENGL && !config::EmulateFramebuffer) || System == COORD_DIRECTX ? -1 : 1; - constexpr int rttFlipY = System == COORD_DIRECTX ? -1 : 1; - constexpr int framebufferFlipY = System == COORD_DIRECTX ? -1 : 1; + constexpr int flipY = System == COORD_DIRECTX ? -1 : 1; renderViewport = { width == 0 ? settings.display.width : width, height == 0 ? settings.display.height : height }; this->renderingContext = renderingContext; @@ -114,8 +112,8 @@ class TransformMatrix if (renderingContext->scaler_ctl.hscale) dcViewport.x *= 2; dcViewport.y = (float)(renderingContext->fb_Y_CLIP.max - renderingContext->fb_Y_CLIP.min + 1); - normalMatrix = glm::translate(glm::vec3(-1, -rttFlipY, 0)) - * glm::scale(glm::vec3(2.0f / dcViewport.x, 2.0f / dcViewport.y * rttFlipY, 1.f)); + normalMatrix = glm::translate(glm::vec3(-1, -flipY, 0)) + * glm::scale(glm::vec3(2.0f / dcViewport.x, 2.0f / dcViewport.y * flipY, 1.f)); scissorMatrix = normalMatrix; sidebarWidth = 0; } @@ -140,9 +138,9 @@ class TransformMatrix else sidebarWidth = 0; float x_coef = 2.0f / dcViewport.x; - float y_coef = 2.0f / dcViewport.y * screenFlipY; + float y_coef = 2.0f / dcViewport.y * flipY; - glm::mat4 trans = glm::translate(glm::vec3(-1 + 2 * sidebarWidth, -screenFlipY, 0)); + glm::mat4 trans = glm::translate(glm::vec3(-1 + 2 * sidebarWidth, -flipY, 0)); normalMatrix = trans * glm::scale(glm::vec3(x_coef, y_coef, 1.f)); @@ -152,15 +150,15 @@ class TransformMatrix normalMatrix = glm::scale(glm::vec3(1, 1, 1 / config::ExtraDepthScale)) * normalMatrix; - glm::mat4 vp_trans = glm::translate(glm::vec3(1, framebufferFlipY, 0)); + glm::mat4 vp_trans = glm::translate(glm::vec3(1, flipY, 0)); if (renderingContext->isRTT) { - vp_trans = glm::scale(glm::vec3(dcViewport.x / 2, dcViewport.y / 2 * framebufferFlipY, 1.f)) + vp_trans = glm::scale(glm::vec3(dcViewport.x / 2, dcViewport.y / 2 * flipY, 1.f)) * vp_trans; } else { - vp_trans = glm::scale(glm::vec3(renderViewport.x / 2, renderViewport.y / 2 * framebufferFlipY, 1.f)) + vp_trans = glm::scale(glm::vec3(renderViewport.x / 2, renderViewport.y / 2 * flipY, 1.f)) * vp_trans; } viewportMatrix = vp_trans * normalMatrix;