From ffe145c2eb7229e673b0c0fb6364ffa41fe30c74 Mon Sep 17 00:00:00 2001 From: Ethan Lee Date: Thu, 25 Jul 2019 15:20:34 -0400 Subject: [PATCH] Replace glProgramViewportFlip with glProgramViewportInfo --- mojoshader.h | 25 ++++++++-- mojoshader_opengl.c | 80 +++++++++++++++++++++--------- profiles/mojoshader_profile_glsl.c | 7 ++- 3 files changed, 83 insertions(+), 29 deletions(-) diff --git a/mojoshader.h b/mojoshader.h index eb0803ae..a289c7a1 100644 --- a/mojoshader.h +++ b/mojoshader.h @@ -3163,10 +3163,27 @@ DECLSPEC void MOJOSHADER_glSetVertexAttribDivisor(MOJOSHADER_usage usage, */ 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 diff --git a/mojoshader_opengl.c b/mojoshader_opengl.c index 94413fcc..7fb3d8b8 100644 --- a/mojoshader_opengl.c +++ b/mojoshader_opengl.c @@ -111,6 +111,10 @@ struct MOJOSHADER_glProgram 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 @@ struct MOJOSHADER_glContext PFNGLSHADERSOURCEPROC glShaderSource; PFNGLUNIFORM1IPROC glUniform1i; PFNGLUNIFORM1IVPROC glUniform1iv; + PFNGLUNIFORM2FPROC glUniform2f; #ifdef MOJOSHADER_FLIP_RENDERTARGET PFNGLUNIFORM1FPROC glUniform1f; #endif @@ -579,6 +584,7 @@ static void impl_GLSL_FinalInitProgram(MOJOSHADER_glProgram *program) 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 @@ static void lookup_entry_points(MOJOSHADER_glGetProcAddress lookup, void *d) 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 @@ void MOJOSHADER_glProgramReady(void) } // 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 @@ void MOJOSHADER_glDestroyContext(MOJOSHADER_glContext *_ctx) } // 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 diff --git a/profiles/mojoshader_profile_glsl.c b/profiles/mojoshader_profile_glsl.c index 2f196494..e20c1be8 100644 --- a/profiles/mojoshader_profile_glsl.c +++ b/profiles/mojoshader_profile_glsl.c @@ -1037,8 +1037,11 @@ void emit_GLSL_attribute(Context *ctx, RegisterType regtype, int regnum, } // 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 {