diff --git a/MacGLide/OpenGLide/grguBuffer.cpp b/MacGLide/OpenGLide/grguBuffer.cpp index 74cfb6f..fefd864 100644 --- a/MacGLide/OpenGLide/grguBuffer.cpp +++ b/MacGLide/OpenGLide/grguBuffer.cpp @@ -17,6 +17,110 @@ #include "GLRenderUpdateState.h" #include "GLUtil.h" +// Write colored pixels only +void gapfixSetSimpleColorState() +{ + // Disable the cull mode + glDisable(GL_CULL_FACE); + // Disable clip volume hint manually to avoid recursion + if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) + { + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); + } + // Blend + glDisable(GL_BLEND); + SetBlendState(); + // Alpha + glDisable(GL_ALPHA_TEST); + SetChromaKeyAndAlphaState(); + // disable depth buffer + glDepthMask(false); + // Enable colormask + glColorMask(true, true, true, false); + // Needed for displaying in-game menus + if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) + { + glDisable(GL_DEPTH_TEST); + } + if (InternalConfig.EXT_secondary_color) + { + glDisable(GL_COLOR_SUM_EXT); + } + if (OpenGL.Fog && OpenGL.FogTextureUnit) + { + glActiveTextureARB(OpenGL.FogTextureUnit); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.FogTextureUnit); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(4, GL_FLOAT, 0, NULL); + } + glDisable(GL_TEXTURE_2D); + OpenGL.FogTextureUnitEnabledState = false; + SetFogModeState(); + } + for(long unit_index = 1; unit_index >= 0; unit_index--) + { + glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + if (InternalConfig.EXT_compiled_vertex_array) + { + glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(4, GL_FLOAT, 0, NULL); + } + glDisable(GL_TEXTURE_2D); + OpenGL.ColorAlphaUnitColorEnabledState[unit_index] = false; + OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = false; + } + SetTextureState(); + SetColorCombineState(); + SetAlphaCombineState(); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + VERIFY_TEXTURE_ENABLED_STATE(); +} + +void gapfixRestoreFromSimpleColorState() +{ + // Restore state + switch (Glide.State.CullMode) + { + case GR_CULL_DISABLE: + break; + case GR_CULL_NEGATIVE: + case GR_CULL_POSITIVE: + glEnable(GL_CULL_FACE); + break; + } + if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) + { + glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_NICEST); + } + // restore previous state + if (OpenGL.DepthBufferWritting) + { + glDepthMask(true); + } + const bool colormask = Glide.State.ColorMask; + glColorMask(colormask, colormask, colormask, Glide.State.AlphaMask); + if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) + { + glEnable(GL_DEPTH_TEST); + } + // Restore colormask + bool rgb = Glide.State.ColorMask; + glColorMask(rgb, rgb, rgb, Glide.State.AlphaMask); + if (InternalConfig.EXT_secondary_color) + { + glEnable(GL_COLOR_SUM_EXT); + } + // Return to normal rendering + glStencilFunc(GL_ALWAYS, 0x02, 0x03); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + + VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); + VERIFY_TEXTURE_ENABLED_STATE(); +} //************************************************* //* Clear buffer @@ -71,6 +175,48 @@ grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU16 depth ) glReportError(); glDisable( GL_SCISSOR_TEST ); } + + // In Tomb Raider 1, the last column/row of framebuffer pixels contains gapfix rendering artefacts. + // This happens, because TR1 doesn't render the last column/row. Because the gapfix actually renders + // into this area the stencil buffer value must be set to "pixel normally renderded" + if ((InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled) && (s_GlideApplication.GetType() == GlideApplication::TombRaiderI)) + { + // write "pixel normally rendered" stencil value in the last column/row + gapfixSetSimpleColorState(); + if (InternalConfig.GapFix & OpenGLideGapFixFlag_Debug) + { + // Write Cyan colored pixels + GLfloat clearcolor[] = + { + 0.0f, 1.0f, 1.0f, 0.0f + }; + glColorMask(true, true, true, false); + glColor4fv(clearcolor); + } + // Stencil already set to "pixel normally rendered" + const GLfloat xmin = 0.0; + const GLfloat ymin = 0.0; + const GLfloat xmax = Glide.WindowWidth; + const GLfloat ymax = Glide.WindowHeight; + const GLfloat depth = 1.0f; + // Because we're rendering a quad, one more line maybe not gap-fixed + // Bottom + glBegin(GL_QUADS); + glVertex3f(xmin, ymax - 1.0, depth); + glVertex3f(xmax, ymax - 1.0, depth); + glVertex3f(xmax, ymax, depth); + glVertex3f(xmin, ymax, depth); + glEnd(); + // right + glBegin(GL_QUADS); + glVertex3f(xmax - 1.0, ymin, depth); + glVertex3f(xmax - 1.0, ymax, depth); + glVertex3f(xmax, ymax, depth); + glVertex3f(xmax, ymin, depth); + glEnd(); + gapfixRestoreFromSimpleColorState(); + } + glReportError(); } @@ -78,18 +224,18 @@ grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU16 depth ) //* Swaps front and back Buffer //************************************************* FX_ENTRY void FX_CALL -grBufferSwap( int swap_interval ) +grBufferSwap(int swap_interval) { #if defined( OGL_DONE ) || defined( OGL_COMBINE ) GlideMsg( "grBufferSwap( %d )\n", swap_interval ); #endif glReportErrors("grBufferSwap"); - RenderDrawTriangles( ); + RenderDrawTriangles(); #ifdef OGL_DEBUG static float Temp = 1.0f; - if ( OGLRender.FrameTriangles > OGLRender.MaxTriangles ) + if (OGLRender.FrameTriangles > OGLRender.MaxTriangles) { OGLRender.MaxTriangles = OGLRender.FrameTriangles; } @@ -101,65 +247,7 @@ grBufferSwap( int swap_interval ) if (InternalConfig.GapFix & OpenGLideGapFixFlag_Enabled) { - // Disable the cull mode - glDisable(GL_CULL_FACE); - // Disable clip volume hint manually to avoid recursion - if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) - { - glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); - } - // Blend - glDisable(GL_BLEND); - SetBlendState(); - // Alpha - glDisable(GL_ALPHA_TEST); - SetChromaKeyAndAlphaState(); - // disable depth buffer - glDepthMask(false); - // Enable colormask - glColorMask(true, true, true, false); - // Needed for displaying in-game menus - if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) - { - glDisable(GL_DEPTH_TEST); - } - if (InternalConfig.EXT_secondary_color) - { - glDisable(GL_COLOR_SUM_EXT); - } - if (OpenGL.Fog && OpenGL.FogTextureUnit) - { - glActiveTextureARB(OpenGL.FogTextureUnit); - if (InternalConfig.EXT_compiled_vertex_array) - { - glClientActiveTextureARB(OpenGL.FogTextureUnit); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(4, GL_FLOAT, 0, NULL); - } - glDisable(GL_TEXTURE_2D); - OpenGL.FogTextureUnitEnabledState = false; - SetFogModeState(); - } - for(long unit_index = 1; unit_index >= 0; unit_index--) - { - glActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); - if (InternalConfig.EXT_compiled_vertex_array) - { - glClientActiveTextureARB(OpenGL.ColorAlphaUnit1 + unit_index); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(4, GL_FLOAT, 0, NULL); - } - glDisable(GL_TEXTURE_2D); - OpenGL.ColorAlphaUnitColorEnabledState[unit_index] = false; - OpenGL.ColorAlphaUnitAlphaEnabledState[unit_index] = false; - } - SetTextureState(); - SetColorCombineState(); - SetAlphaCombineState(); - - VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); - VERIFY_TEXTURE_ENABLED_STATE(); - + gapfixSetSimpleColorState(); glStencilFunc(GL_NOTEQUAL, 0x02, 0x03); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glReportError(); @@ -175,58 +263,31 @@ grBufferSwap( int swap_interval ) clearcolor[0] = 1.0f; } } - GLfloat depth = 1.0f; + // @todo: Turn off clipping + const FxU32 xmin = 0; + const FxU32 ymin = 0; + const GlideApplication::Type application = s_GlideApplication.GetType(); + const FxU32 xmax = Glide.WindowWidth - ((application == GlideApplication::TombRaiderI) ? 1 : 0); + const FxU32 ymax = Glide.WindowHeight - ((application == GlideApplication::TombRaiderI) ? 1 : 0); + const GLfloat depth = 1.0f; glBegin(GL_QUADS); glColor4fv(clearcolor); - glVertex3f(Glide.State.ClipMinX, Glide.State.ClipMinY, depth); + glVertex3f(xmin, ymin, depth); glColor4fv(clearcolor); - glVertex3f(Glide.State.ClipMaxX, Glide.State.ClipMinY, depth); + glVertex3f(xmax, ymin, depth); glColor4fv(clearcolor); - glVertex3f(Glide.State.ClipMaxX, Glide.State.ClipMaxY, depth); + glVertex3f(xmax, ymax, depth); glColor4fv(clearcolor); - glVertex3f(Glide.State.ClipMinX, Glide.State.ClipMaxY, depth); + glVertex3f(xmin, ymax, depth); glEnd(); - glStencilFunc(GL_ALWAYS, 0x02, 0x03); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - // Restore state - switch (Glide.State.CullMode) - { - case GR_CULL_DISABLE: - break; - case GR_CULL_NEGATIVE: - case GR_CULL_POSITIVE: - glEnable(GL_CULL_FACE); - break; - } - if (InternalConfig.EXT_clip_volume_hint && OpenGL.ClipVerticesEnabledState) - { - glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_NICEST); - } - // restore previous state - if (OpenGL.DepthBufferWritting) - { - glDepthMask(true); - } - if (Glide.State.DepthBufferMode != GR_DEPTHBUFFER_DISABLE) - { - glEnable(GL_DEPTH_TEST); - } - // Restore colormask - bool rgb = Glide.State.ColorMask; - glColorMask(rgb, rgb, rgb, Glide.State.AlphaMask); - if (InternalConfig.EXT_secondary_color) - { - glEnable( GL_COLOR_SUM_EXT ); - } - VERIFY_ACTIVE_TEXTURE_UNIT(OpenGL.ColorAlphaUnit1); - VERIFY_TEXTURE_ENABLED_STATE(); + gapfixRestoreFromSimpleColorState(); } // @todo: setting the swap interval doesn't seem to work - // - the 3dfx splash animation appears a bit to fast + // - the 3Dfx splash animation appears a bit to fast // and using higher values doesn't work - // -> might be a bug in Classic + // - happens in Classic as well as in OS9 native GLint swap = swap_interval; aglSetInteger(pWindowInfo->aglContext, AGL_SWAP_INTERVAL, &swap); aglReportError();