Replace glProgramViewportFlip with glProgramViewportInfo
authorEthan Lee <flibitijibibo@flibitijibibo.com>
Thu, 25 Jul 2019 15:20:34 -0400
changeset 1210 c586d4590241
parent 1209 2e37299b13d8
child 1211 74c594099cba
Replace glProgramViewportFlip with glProgramViewportInfo
mojoshader.h
mojoshader_opengl.c
profiles/mojoshader_profile_glsl.c
--- a/mojoshader.h	Thu Jul 25 15:17:31 2019 -0400
+++ b/mojoshader.h	Thu Jul 25 15:20:34 2019 -0400
@@ -3163,10 +3163,27 @@
  */
 DECLSPEC void MOJOSHADER_glProgramReady(void);
 
-#ifdef MOJOSHADER_FLIP_RENDERTARGET
-// !!! FIXME: Document me.
-DECLSPEC void MOJOSHADER_glProgramViewportFlip(int flip);
-#endif
+/*
+ * Provide information about the current viewport to the prepared shader
+ *  program.
+ *
+ * There are numerous components of OpenGL and Direct3D where the coordinate
+ *  systems do not match, and so the vertex/pixel shaders have to be modified to
+ *  compensate for these mismatches (for example, gl_FragCoord requires some
+ *  additional math on the Y coordinate to match vPos when rendering to the
+ *  backbuffer). Call this after MOJOSHADER_glProgramReady to apply all of the
+ *  relevant coordinate fixups at once.
+ *
+ * This call is NOT thread safe! As most OpenGL implementations are not thread
+ *  safe, you should probably only call this from the same thread that created
+ *  the GL context.
+ *
+ * This call requires a valid MOJOSHADER_glContext to have been made current,
+ *  or it will crash your program. See MOJOSHADER_glMakeContextCurrent().
+ */
+DECLSPEC void MOJOSHADER_glProgramViewportInfo(int viewportW, int viewportH,
+                                               int backbufferW, int backbufferH,
+                                               int renderTargetBound);
 
 /*
  * Free the resources of a linked program. This will delete the GL object
--- a/mojoshader_opengl.c	Thu Jul 25 15:17:31 2019 -0400
+++ b/mojoshader_opengl.c	Thu Jul 25 15:20:34 2019 -0400
@@ -111,6 +111,10 @@
     GLint ps_float4_loc;
     GLint ps_int4_loc;
     GLint ps_bool_loc;
+
+    // Numerous fixes for coordinate system mismatches
+    GLint ps_vpos_flip_loc;
+    int current_vpos_flip[2];
 #ifdef MOJOSHADER_FLIP_RENDERTARGET
     GLint vs_flip_loc;
     int current_flip;
@@ -228,6 +232,7 @@
     PFNGLSHADERSOURCEPROC glShaderSource;
     PFNGLUNIFORM1IPROC glUniform1i;
     PFNGLUNIFORM1IVPROC glUniform1iv;
+    PFNGLUNIFORM2FPROC glUniform2f;
 #ifdef MOJOSHADER_FLIP_RENDERTARGET
     PFNGLUNIFORM1FPROC glUniform1f;
 #endif
@@ -579,6 +584,7 @@
     program->ps_float4_loc = glsl_uniform_loc(program, "ps_uniforms_vec4");
     program->ps_int4_loc = glsl_uniform_loc(program, "ps_uniforms_ivec4");
     program->ps_bool_loc = glsl_uniform_loc(program, "ps_uniforms_bool");
+    program->ps_vpos_flip_loc = glsl_uniform_loc(program, "vposFlip");
 #ifdef MOJOSHADER_FLIP_RENDERTARGET
     program->vs_flip_loc = glsl_uniform_loc(program, "vpFlip");
 #endif
@@ -985,6 +991,7 @@
     DO_LOOKUP(opengl_2, PFNGLSHADERSOURCEPROC, glShaderSource);
     DO_LOOKUP(opengl_2, PFNGLUNIFORM1IPROC, glUniform1i);
     DO_LOOKUP(opengl_2, PFNGLUNIFORM1IVPROC, glUniform1iv);
+    DO_LOOKUP(opengl_2, PFNGLUNIFORM2FPROC, glUniform2f);
 #ifdef MOJOSHADER_FLIP_RENDERTARGET
     DO_LOOKUP(opengl_2, PFNGLUNIFORM1FPROC, glUniform1f);
 #endif
@@ -2557,6 +2564,56 @@
 } // MOJOSHADER_glProgramReady
 
 
+void MOJOSHADER_glProgramViewportInfo(int viewportW, int viewportH,
+                                      int backbufferW, int backbufferH,
+                                      int renderTargetBound)
+{
+    int vposFlip[2];
+
+    /* The uniform is only going to exist if VPOS is used! */
+    if (ctx->bound_program->ps_vpos_flip_loc != -1)
+    {
+        if (renderTargetBound)
+        {
+            vposFlip[0] = 1;
+            vposFlip[1] = 0;
+        } // if
+        else
+        {
+            vposFlip[0] = -1;
+            vposFlip[1] = backbufferH;
+        } // else
+        if ( (ctx->bound_program->current_vpos_flip[0] != vposFlip[0]) ||
+             (ctx->bound_program->current_vpos_flip[1] != vposFlip[1]) )
+        {
+            ctx->glUniform2f(
+                ctx->bound_program->ps_vpos_flip_loc,
+                (float) vposFlip[0],
+                (float) vposFlip[1]
+            );
+            ctx->bound_program->current_vpos_flip[0] = vposFlip[0];
+            ctx->bound_program->current_vpos_flip[1] = vposFlip[1];
+        } // if
+    } // if
+
+#ifdef MOJOSHADER_FLIP_RENDERTARGET
+    assert(ctx->bound_program->vs_flip_loc != -1);
+
+    /* Some compilers require that vpFlip be a float value, rather than int.
+     * However, there's no real reason for it to be a float in the API, so we
+     * do a cast in here. That's not so bad, right...?
+     * -flibit
+     */
+    const int flip = renderTargetBound ? -1 : 1;
+    if (flip != ctx->bound_program->current_flip)
+    {
+        ctx->glUniform1f(ctx->bound_program->vs_flip_loc, (float) flip);
+        ctx->bound_program->current_flip = flip;
+    } // if
+#endif
+} // MOJOSHADER_glViewportInfo
+
+
 void MOJOSHADER_glDeleteProgram(MOJOSHADER_glProgram *program)
 {
     program_unref(program);
@@ -2601,29 +2658,6 @@
 } // MOJOSHADER_glDestroyContext
 
 
-#ifdef MOJOSHADER_FLIP_RENDERTARGET
-
-
-void MOJOSHADER_glProgramViewportFlip(int flip)
-{
-    assert(ctx->bound_program->vs_flip_loc != -1);
-
-    /* Some compilers require that vpFlip be a float value, rather than int.
-     * However, there's no real reason for it to be a float in the API, so we
-     * do a cast in here. That's not so bad, right...?
-     * -flibit
-     */
-    if (flip != ctx->bound_program->current_flip)
-    {
-        ctx->glUniform1f(ctx->bound_program->vs_flip_loc, (float) flip);
-        ctx->bound_program->current_flip = flip;
-    } // if
-}
-
-
-#endif
-
-
 #ifdef MOJOSHADER_EFFECT_SUPPORT
 
 
--- a/profiles/mojoshader_profile_glsl.c	Thu Jul 25 15:17:31 2019 -0400
+++ b/profiles/mojoshader_profile_glsl.c	Thu Jul 25 15:20:34 2019 -0400
@@ -1037,8 +1037,11 @@
             } // if
             else if (mt == MISCTYPE_TYPE_POSITION)
             {
-                index_str[0] = '\0';  // no explicit number.
-                usage_str = "gl_FragCoord";  // !!! FIXME: is this the same coord space as D3D?
+                push_output(ctx, &ctx->globals);
+                output_line(ctx, "uniform vec2 vposFlip;");
+                output_line(ctx, "vec4 %s = floor(vec4(gl_FragCoord.x, (gl_FragCoord.y * vposFlip.x) + vposFlip.y, gl_FragCoord.z, gl_FragCoord.w));", var);
+                pop_output(ctx);
+                return;
             } // else if
             else
             {