R_View_UpdateEntityVisible();
}
-void R_ResetViewRendering(void)
+void R_SetupView(const matrix4x4_t *matrix)
+{
+ if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
+ GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
+ else
+ GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
+
+ GL_SetupView_Orientation_FromEntity(matrix);
+}
+
+void R_ResetViewRendering2D(void)
{
if (gl_support_fragment_shader)
{
qglUseProgramObjectARB(0);CHECKGLERROR
}
+ DrawQ_Finish();
+
// GL is weird because it's bottom to top, r_view.y is top to bottom
qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ GL_Color(1, 1, 1, 1);
GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_AlphaTest(false);
GL_ScissorTest(false);
GL_DepthMask(false);
GL_DepthTest(false);
R_Mesh_Matrix(&identitymatrix);
R_Mesh_ResetTextureState();
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ qglStencilMask(~0);CHECKGLERROR
+ qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
+ qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
+}
+
+void R_ResetViewRendering3D(void)
+{
+ if (gl_support_fragment_shader)
+ {
+ qglUseProgramObjectARB(0);CHECKGLERROR
+ }
+
+ DrawQ_Finish();
+
+ // GL is weird because it's bottom to top, r_view.y is top to bottom
+ qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
+ R_SetupView(&r_view.matrix);
+ GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ GL_Color(1, 1, 1, 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_AlphaTest(false);
+ GL_ScissorTest(true);
+ GL_DepthMask(true);
+ GL_DepthTest(true);
+ R_Mesh_Matrix(&identitymatrix);
+ R_Mesh_ResetTextureState();
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ qglStencilMask(~0);CHECKGLERROR
+ qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
+ qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
}
/*
"#endif // FRAGMENT_SHADER\n"
*/
-void R_SetupView(const matrix4x4_t *matrix)
-{
- if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
- GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
- else
- GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
-
- GL_SetupView_Orientation_FromEntity(matrix);
-}
-
void R_RenderScene(void);
void R_Bloom_StartFrame(void)
{
r_refdef.stats.bloom++;
- R_ResetViewRendering();
+ R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
R_Mesh_TexCoordPointer(0, 2, r_bloomstate.screentexcoord2f);
r_refdef.stats.bloom++;
- R_ResetViewRendering();
+ R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
// TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
// TODO: add exposure compensation features
+ // TODO: add fp16 framebuffer support
r_view.colorscale = r_bloom_colorscale.value * r_hdr_scenebrightness.value;
R_RenderScene();
- R_ResetViewRendering();
+ R_ResetViewRendering2D();
R_Bloom_CopyHDRTexture();
R_Bloom_MakeTexture();
- R_ResetViewRendering();
- GL_ScissorTest(true);
- GL_DepthMask(true);
- GL_DepthTest(true);
+ R_ResetViewRendering3D();
+
R_ClearScreen();
if (r_timereport_active)
R_TimeReport("clear");
+
// restore the view settings
r_view.width = oldwidth;
r_view.height = oldheight;
// render high dynamic range bloom effect
// the bloom texture was made earlier this render, so we just need to
// blend it onto the screen...
- R_ResetViewRendering();
+ R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
GL_Color(1, 1, 1, 1);
R_Bloom_MakeTexture();
// put the original screen image back in place and blend the bloom
// texture on it
- R_ResetViewRendering();
+ R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
GL_Color(1, 1, 1, 1);
if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
{
// apply a color tint to the whole view
- R_ResetViewRendering();
+ R_ResetViewRendering2D();
R_Mesh_VertexPointer(r_screenvertex3f);
R_Mesh_ColorPointer(NULL);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
+ R_Shadow_UpdateWorldLightSelection();
+
CHECKGLERROR
if (r_timereport_active)
R_TimeReport("setup");
if (r_timereport_active)
R_TimeReport("visibility");
- R_ResetViewRendering();
- GL_ScissorTest(true);
- GL_DepthMask(true);
- GL_DepthTest(true);
+ R_ResetViewRendering3D();
+
R_ClearScreen();
if (r_timereport_active)
R_TimeReport("clear");
extern void R_DrawPortals (void);
void R_RenderScene(void)
{
- DrawQ_Finish();
-
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- CHECKGLERROR
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
-
- R_ResetViewRendering();
- R_SetupView(&r_view.matrix);
+ R_ResetViewRendering3D();
R_MeshQueue_BeginScene();
- R_Shadow_UpdateWorldLightSelection();
-
R_SkyStartFrame();
Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.time) * 0.025 * r_waterscroll.value, sin(r_refdef.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
{
R_DrawModelShadows();
+ R_ResetViewRendering3D();
+
// don't let sound skip if going slow
if (r_refdef.extraupdate)
S_ExtraUpdate ();
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- CHECKGLERROR
- if (gl_support_fragment_shader)
- {
- qglUseProgramObjectARB(0);CHECKGLERROR
- }
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
+ R_ResetViewRendering2D();
}
/*
GL_DepthMask(true);
}
GL_DepthTest(!(ent->effects & EF_NODEPTHTEST));
+ GL_CullFace((ent->flags & RENDER_NOCULLFACE) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
R_Mesh_VertexPointer(nomodelvertex3f);
if (r_refdef.fogenabled)
{
const int *elements;
vec3_t v;
CHECKGLERROR
- GL_DepthTest(true);
+ GL_DepthTest(!r_showdisabledepthtest.integer);
GL_DepthMask(true);
- if (r_showdisabledepthtest.integer)
- {
- qglDepthFunc(GL_ALWAYS);CHECKGLERROR
- }
GL_BlendFunc(GL_ONE, GL_ZERO);
R_Mesh_ColorPointer(NULL);
R_Mesh_ResetTextureState();
}
}
rsurface_texture = NULL;
- if (r_showdisabledepthtest.integer)
- {
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- }
}
}
#define GL_CLAMP_TO_EDGE 0x812F
#endif
+//GL_ATI_separate_stencil
+extern int gl_support_separatestencil;
+#ifndef GL_STENCIL_BACK_FUNC
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#endif
+extern void (GLAPIENTRY *qglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum);
+extern void (GLAPIENTRY *qglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint);
+
//GL_EXT_stencil_two_side
#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
{
R_SHADOW_RENDERMODE_NONE,
R_SHADOW_RENDERMODE_STENCIL,
+ R_SHADOW_RENDERMODE_SEPARATESTENCIL,
R_SHADOW_RENDERMODE_STENCILTWOSIDE,
R_SHADOW_RENDERMODE_LIGHT_VERTEX,
R_SHADOW_RENDERMODE_LIGHT_DOT3,
cvar_t r_shadow_shadow_polygonfactor = {0, "r_shadow_shadow_polygonfactor", "0", "how much to enlarge shadow volume polygons when rendering (should be 0!)"};
cvar_t r_shadow_shadow_polygonoffset = {0, "r_shadow_shadow_polygonoffset", "1", "how much to push shadow volumes into the distance when rendering, to reduce chances of zfighting artifacts (should not be less than 0)"};
cvar_t r_shadow_texture3d = {0, "r_shadow_texture3d", "1", "use 3D voxel textures for spherical attenuation rather than cylindrical (does not affect r_glsl lighting)"};
+cvar_t gl_ext_separatestencil = {0, "gl_ext_separatetencil", "1", "make use of OpenGL 2.0 glStencilOpSeparate or GL_ATI_separate_stencil extension"};
cvar_t gl_ext_stenciltwoside = {0, "gl_ext_stenciltwoside", "1", "make use of GL_EXT_stenciltwoside extension (NVIDIA only)"};
cvar_t r_editlights = {0, "r_editlights", "0", "enables .rtlights file editing mode"};
cvar_t r_editlights_cursordistance = {0, "r_editlights_cursordistance", "1024", "maximum distance of cursor from eye"};
Cvar_RegisterVariable(&r_shadow_shadow_polygonfactor);
Cvar_RegisterVariable(&r_shadow_shadow_polygonoffset);
Cvar_RegisterVariable(&r_shadow_texture3d);
+ Cvar_RegisterVariable(&gl_ext_separatestencil);
Cvar_RegisterVariable(&gl_ext_stenciltwoside);
if (gamemode == GAME_TENEBRAE)
{
{
if (r_shadow_texture3d.integer && !gl_texture3d)
Cvar_SetValueQuick(&r_shadow_texture3d, 0);
+ if (gl_ext_separatestencil.integer && !gl_support_separatestencil)
+ Cvar_SetValueQuick(&gl_ext_separatestencil, 0);
if (gl_ext_stenciltwoside.integer && !gl_support_stenciltwoside)
Cvar_SetValueQuick(&gl_ext_stenciltwoside, 0);
}
R_Mesh_ColorPointer(NULL);
R_Mesh_ResetTextureState();
GL_BlendFunc(GL_ONE, GL_ZERO);
+ GL_DepthTest(true);
GL_DepthMask(false);
GL_Color(0, 0, 0, 1);
GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
- if (gl_ext_stenciltwoside.integer)
+ if (gl_ext_separatestencil.integer)
+ r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_SEPARATESTENCIL;
+ else if (gl_ext_stenciltwoside.integer)
r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCILTWOSIDE;
else
r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCIL;
}
R_Mesh_ColorPointer(NULL);
R_Mesh_ResetTextureState();
+ GL_DepthTest(true);
+ GL_DepthMask(false);
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ qglStencilMask(~0);CHECKGLERROR
+ qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
+ qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
+ GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
+ GL_Color(1, 1, 1, 1);
+ GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_BlendFunc(GL_ONE, GL_ZERO);
}
void R_Shadow_RenderMode_StencilShadowVolumes(void)
{
CHECKGLERROR
R_Shadow_RenderMode_Reset();
- GL_Color(1, 1, 1, 1);
GL_ColorMask(0, 0, 0, 0);
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_DepthMask(false);
qglPolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
qglDepthFunc(GL_LESS);CHECKGLERROR
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
- qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
r_shadow_rendermode = r_shadow_shadowingrendermode;
- if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE)
+ if (r_shadow_rendermode == R_SHADOW_RENDERMODE_SEPARATESTENCIL)
+ {
+ GL_CullFace(GL_NONE);
+ qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_INCR, GL_KEEP);CHECKGLERROR // quake is backwards, this is front faces
+ qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR // quake is backwards, this is back faces
+ }
+ else if (r_shadow_rendermode == R_SHADOW_RENDERMODE_STENCILTWOSIDE)
{
GL_CullFace(GL_NONE);
qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
qglStencilMask(~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_DECR, GL_KEEP);CHECKGLERROR
}
- else
- {
- GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
- qglStencilMask(~0);CHECKGLERROR
- // this is changed by every shadow render so its value here is unimportant
- qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
- }
GL_Clear(GL_STENCIL_BUFFER_BIT);
r_refdef.stats.lights_clears++;
}
CHECKGLERROR
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- GL_DepthMask(false);
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- //qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
- GL_Color(1, 1, 1, 1);
- GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
- if (transparent)
- {
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- }
- else
+ if (!transparent)
{
qglDepthFunc(GL_EQUAL);CHECKGLERROR
}
if (stenciltest)
{
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+ // only draw light where this geometry was already rendered AND the
+ // stencil is 128 (values other than this mean shadow)
+ qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
}
- else
- {
- qglDisable(GL_STENCIL_TEST);CHECKGLERROR
- }
- qglStencilMask(~0);CHECKGLERROR
- qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
- // only draw light where this geometry was already rendered AND the
- // stencil is 128 (values other than this mean shadow)
- qglStencilFunc(GL_EQUAL, 128, ~0);CHECKGLERROR
r_shadow_rendermode = r_shadow_lightingrendermode;
// do global setup needed for the chosen lighting mode
if (r_shadow_rendermode == R_SHADOW_RENDERMODE_LIGHT_GLSL)
CHECKGLERROR
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_ONE, GL_ONE);
- GL_DepthMask(false);
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ GL_DepthTest(r_showshadowvolumes.integer < 2);
GL_Color(0.0, 0.0125 * r_view.colorscale, 0.1 * r_view.colorscale, 1);
- GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
- if (r_showshadowvolumes.integer >= 2)
- {
- qglDepthFunc(GL_ALWAYS);CHECKGLERROR
- }
- else
- {
- qglDepthFunc(GL_GEQUAL);CHECKGLERROR
- }
- qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ qglPolygonOffset(r_refdef.shadowpolygonfactor, r_refdef.shadowpolygonoffset);CHECKGLERROR
+ GL_CullFace(GL_NONE);
r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLEVOLUMES;
}
CHECKGLERROR
R_Shadow_RenderMode_Reset();
GL_BlendFunc(GL_ONE, GL_ONE);
- GL_DepthMask(false);
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
+ GL_DepthTest(r_showlighting.integer < 2);
GL_Color(0.1 * r_view.colorscale, 0.0125 * r_view.colorscale, 0, 1);
- GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
- if (r_showshadowvolumes.integer >= 2)
- {
- qglDepthFunc(GL_ALWAYS);CHECKGLERROR
- }
- else if (transparent)
- {
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- }
- else
+ if (!transparent)
{
qglDepthFunc(GL_EQUAL);CHECKGLERROR
}
{
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
}
- else
- {
- qglDisable(GL_STENCIL_TEST);CHECKGLERROR
- }
r_shadow_rendermode = R_SHADOW_RENDERMODE_VISIBLELIGHTING;
}
CHECKGLERROR
R_Shadow_RenderMode_Reset();
R_Shadow_RenderMode_ActiveLight(NULL);
- GL_BlendFunc(GL_ONE, GL_ZERO);
GL_DepthMask(true);
- qglPolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);CHECKGLERROR
- //qglDisable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
- GL_Color(1, 1, 1, 1);
- GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
- qglDepthFunc(GL_LEQUAL);CHECKGLERROR
- if (gl_support_stenciltwoside)
- {
- qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
- }
- qglDisable(GL_STENCIL_TEST);CHECKGLERROR
- qglStencilMask(~0);CHECKGLERROR
- qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
- qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
- GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
}
r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
- if (gl_ext_stenciltwoside.integer)
+ if (gl_ext_separatestencil.integer)
+ r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_SEPARATESTENCIL;
+ else if (gl_ext_stenciltwoside.integer)
r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCILTWOSIDE;
else
r_shadow_shadowingrendermode = R_SHADOW_RENDERMODE_STENCIL;
// apply the blend to the shadowed areas
R_Mesh_Draw(0, 4, 2, polygonelements);
- // restore perspective view
- R_SetupView(&r_view.matrix);
+ // restoring the perspective view is done by R_RenderScene
+ //R_SetupView(&r_view.matrix);
// restore other state to normal
- GL_DepthTest(true);
R_Shadow_RenderMode_End();
}
extern cvar_t r_shadow_shadow_polygonoffset;
extern cvar_t r_shadow_singlepassvolumegeneration;
extern cvar_t r_shadow_texture3d;
+extern cvar_t gl_ext_separatestencil;
extern cvar_t gl_ext_stenciltwoside;
void R_Shadow_Init(void);
// GL_EXT_texture_filter_anisotropic
int gl_support_anisotropy = false;
int gl_max_anisotropy = 1;
+// OpenGL2.0 core glStencilOpSeparate, or GL_ATI_separate_stencil
+int gl_support_separatestencil = false;
// GL_EXT_stencil_two_side
int gl_support_stenciltwoside = false;
// GL_EXT_blend_minmax
void (GLAPIENTRY *qglBlendEquationEXT)(GLenum);
+void (GLAPIENTRY *qglStencilOpSeparate)(GLenum, GLenum, GLenum, GLenum);
+void (GLAPIENTRY *qglStencilFuncSeparate)(GLenum, GLenum, GLint, GLuint);
void (GLAPIENTRY *qglActiveStencilFaceEXT)(GLenum);
void (GLAPIENTRY *qglDeleteObjectARB)(GLhandleARB obj);
{NULL, NULL}
};
+static dllfunction_t atiseparatestencilfuncs[] =
+{
+ {"glStencilOpSeparateATI", (void **) &qglStencilOpSeparate},
+ {"glStencilFuncSeparateATI", (void **) &qglStencilFuncSeparate},
+ {NULL, NULL}
+};
+
+static dllfunction_t gl2separatestencilfuncs[] =
+{
+ {"glStencilOpSeparate", (void **) &qglStencilOpSeparate},
+ {"glStencilFuncSeparate", (void **) &qglStencilFuncSeparate},
+ {NULL, NULL}
+};
+
static dllfunction_t stenciltwosidefuncs[] =
{
{"glActiveStencilFaceEXT", (void **) &qglActiveStencilFaceEXT},
gl_support_clamptoedge = false;
gl_support_anisotropy = false;
gl_max_anisotropy = 1;
+ gl_support_separatestencil = false;
gl_support_stenciltwoside = false;
gl_support_ext_blend_minmax = false;
gl_support_ext_blend_subtract = false;
gl_support_ext_blend_minmax = GL_CheckExtension("GL_EXT_blend_minmax", blendequationfuncs, "-noblendminmax", false);
gl_support_ext_blend_subtract = GL_CheckExtension("GL_EXT_blend_subtract", blendequationfuncs, "-noblendsubtract", false);
+// COMMANDLINEOPTION: GL: -noseparatestencil disables use of OpenGL2.0 glStencilOpSeparate and GL_ATI_separate_stencil extensions (accelerates shadow rendering)
+ if (!(gl_support_separatestencil = GL_CheckExtension("glStencilOpSeparate", gl2separatestencilfuncs, "-noseparatestencil", false)))
+ gl_support_separatestencil = GL_CheckExtension("GL_ATI_separate_stencil", atiseparatestencilfuncs, "-noseparatestencil", false);
// COMMANDLINEOPTION: GL: -nostenciltwoside disables GL_EXT_stencil_two_side (accelerates shadow rendering)
gl_support_stenciltwoside = GL_CheckExtension("GL_EXT_stencil_two_side", stenciltwosidefuncs, "-nostenciltwoside", false);