diff --git a/source/lib/glext_funcs.h b/source/lib/glext_funcs.h index 6dff419260..a24a3c81e9 100644 --- a/source/lib/glext_funcs.h +++ b/source/lib/glext_funcs.h @@ -69,6 +69,9 @@ FUNC2(void, glMultiTexCoord3fARB, glMultiTexCoord3f, "1.3", (int, float, float, FUNC2(void, glActiveTextureARB, glActiveTexture, "1.3", (int)) FUNC2(void, glClientActiveTextureARB, glClientActiveTexture, "1.3", (int)) +// GL_EXT_blend_color / GL1.4 (optional in 1.2): +FUNC2(void, glBlendColorEXT, glBlendColor, "1.4", (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)); + // GL_ARB_vertex_buffer_object / GL1.5: FUNC2(void, glBindBufferARB, glBindBuffer, "1.5", (int target, GLuint buffer)) FUNC2(void, glDeleteBuffersARB, glDeleteBuffers, "1.5", (GLsizei n, const GLuint* buffers)) diff --git a/source/lib/ogl.cpp b/source/lib/ogl.cpp index 4e16a94e7f..442870aa10 100644 --- a/source/lib/ogl.cpp +++ b/source/lib/ogl.cpp @@ -145,6 +145,12 @@ static bool isImplementedInCore(const char* ext) MATCH(GL_EXT_texture_lod_bias); MATCH(GL_ARB_texture_mirrored_repeat); MATCH(GL_ARB_window_pos); + + // These extensions were added to GL 1.2, but as part of the optional + // imaging subset; they're only guaranteed as of GL 1.4: + MATCH(GL_EXT_blend_color); + MATCH(GL_EXT_blend_minmax); + MATCH(GL_EXT_blend_subtract); } if(have_13) { @@ -169,9 +175,6 @@ static bool isImplementedInCore(const char* ext) MATCH(GL_SGIS_texture_lod); MATCH(GL_EXT_draw_range_elements); // Skip the extensions that only affect the imaging subset - MATCH(GL_EXT_blend_color); - MATCH(GL_EXT_blend_minmax); - MATCH(GL_EXT_blend_subtract); } #undef MATCH diff --git a/source/lib/sysdep/os/win/wsdl.cpp b/source/lib/sysdep/os/win/wsdl.cpp index db61618f99..ebfe4e96cc 100644 --- a/source/lib/sysdep/os/win/wsdl.cpp +++ b/source/lib/sysdep/os/win/wsdl.cpp @@ -259,6 +259,7 @@ static HGLRC hGLRC = (HGLRC)INVALID_HANDLE_VALUE; // set via SDL_GL_SetAttribute: static int depthBufferBits = 24; +static int stencilBufferBits = 0; static int vsyncEnabled = 1; int SDL_GL_SetAttribute(SDL_GLattr attr, int value) @@ -269,6 +270,10 @@ int SDL_GL_SetAttribute(SDL_GLattr attr, int value) depthBufferBits = value; break; + case SDL_GL_STENCIL_SIZE: + stencilBufferBits = value; + break; + case SDL_GL_SWAP_CONTROL: vsyncEnabled = value; break; @@ -313,7 +318,7 @@ static void video_SetPixelFormat(HDC g_hDC, int bpp) } const BYTE cAccumBits = 0; const BYTE cDepthBits = (BYTE)depthBufferBits; - const BYTE cStencilBits = 0; + const BYTE cStencilBits = (BYTE)stencilBufferBits; const BYTE cAuxBuffers = 0; PIXELFORMATDESCRIPTOR pfd = diff --git a/source/lib/sysdep/os/win/wsdl.h b/source/lib/sysdep/os/win/wsdl.h index c46d6fd6fc..d3364ef6b4 100644 --- a/source/lib/sysdep/os/win/wsdl.h +++ b/source/lib/sysdep/os/win/wsdl.h @@ -57,6 +57,7 @@ LIB_API void SDL_Quit(); typedef enum { SDL_GL_DEPTH_SIZE, + SDL_GL_STENCIL_SIZE, SDL_GL_DOUBLEBUFFER, // ignored - always double buffered SDL_GL_SWAP_CONTROL } diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index 7e921fd137..5a338091b9 100644 --- a/source/renderer/Renderer.cpp +++ b/source/renderer/Renderer.cpp @@ -1205,6 +1205,11 @@ void CRenderer::RenderSilhouettes() float silhouetteAlpha = 0.75f; + // Silhouette blending requires an almost-universally-supported extension; + // fall back to non-blended if unavailable + if (!ogl_HaveExtension("GL_EXT_blend_color")) + silhouetteAlpha = 1.f; + glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glColorMask(0, 0, 0, 0); @@ -1245,10 +1250,10 @@ void CRenderer::RenderSilhouettes() // a pixel once (using the colour of whatever model happens to be drawn first). glEnable(GL_BLEND); glBlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); - glBlendColor(0, 0, 0, silhouetteAlpha); + pglBlendColorEXT(0, 0, 0, silhouetteAlpha); glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_NOTEQUAL, 1, -1); + glStencilFunc(GL_NOTEQUAL, 1, (GLuint)-1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } @@ -1265,11 +1270,17 @@ void CRenderer::RenderSilhouettes() // Restore state glDepthFunc(GL_LEQUAL); - glDepthMask(1); - glDisable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBlendColor(0, 0, 0, 0); - glDisable(GL_STENCIL_TEST); + if (silhouetteAlpha == 1.f) + { + glDepthMask(1); + } + else + { + glDisable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + pglBlendColorEXT(0, 0, 0, 0); + glDisable(GL_STENCIL_TEST); + } } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp index 23a7e941d4..97c2d0cac0 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/ScenarioEditor.cpp @@ -512,6 +512,7 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterfac WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 24, // TODO: wx documentation doesn't say 24 is valid + WX_GL_STENCIL_SIZE, 8, WX_GL_BUFFER_SIZE, 24, // colour bits WX_GL_MIN_ALPHA, 8, // alpha bits 0