Moved two-sided stencil to common code

This commit is contained in:
jpaana 2004-06-13 22:16:55 +00:00
parent a70e1bccb3
commit 8e0ae5c0ff
6 changed files with 182 additions and 186 deletions

View file

@ -53,9 +53,6 @@ void FormatError () {
PFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
PFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
PFNGLSTENCILOPSEPARATEATIPROC qglStencilOpSeparateATI;
PFNGLSTENCILFUNCSEPARATEATIPROC qglStencilFuncSeparateATI;
// ARB_vertex_program
typedef void (APIENTRY * glVertexAttrib1sARBPROC) (GLuint index, GLshort x);
@ -965,15 +962,10 @@ void ARB_CreateShaders()
if ( strstr(gl_extensions, "GL_ATI_pn_triangles") )
{
SAFE_GET_PROC( qglPNTrianglesiATI, PFNGLPNTRIANGLESIATIPROC, "glPNTrianglesiATI");
SAFE_GET_PROC( qglPNTrianglesfATI, PFNGLPNTRIANGLESFATIPROC, "glPNTrianglesfATI");
SAFE_GET_PROC( qglPNTrianglesiATI, PFNGLPNTRIANGLESIATIPROC, "glPNTrianglesiATI");
SAFE_GET_PROC( qglPNTrianglesfATI, PFNGLPNTRIANGLESFATIPROC, "glPNTrianglesfATI");
}
if ( strstr(gl_extensions, "GL_ATI_separate_stencil") )
{
SAFE_GET_PROC( qglStencilOpSeparateATI, PFNGLSTENCILOPSEPARATEATIPROC, "glStencilOpSeparateATI");
SAFE_GET_PROC( qglStencilFuncSeparateATI, PFNGLSTENCILFUNCSEPARATEATIPROC, "glStencilFuncSeparateATI");
}
#endif /* !__APPLE__ && !MACOSX */
glEnable(GL_VERTEX_PROGRAM_ARB);

View file

@ -64,18 +64,6 @@ typedef void (APIENTRY * glProgramLocalParameter4fARBPROC) (GLenum target, GLuin
glProgramLocalParameter4fARBPROC qglProgramLocalParameter4fARB;
#endif
// EXT_stencil_two_side
#ifndef GL_EXT_stencil_two_side
#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
#endif
#ifndef GL_EXT_stencil_two_side
#define GL_EXT_stencil_two_side 1
typedef void (APIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
PFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
#endif
static char bump_vertex_program[] =
"!!VP1.1\n"
"OPTION NV_position_invariant;\n"
@ -536,7 +524,7 @@ void NV3x_EnableBumpShader(const transform_t *tr, const lightobject_t *lo,
if (currentshadowlight->shader->stages[0].texture[0]->gltype == GL_TEXTURE_CUBE_MAP_ARB)
{
NV3x_SetupTcMods(&currentshadowlight->shader->stages[0]);
SH_SetupTcMods(&currentshadowlight->shader->stages[0]);
GL_SetupCubeMapMatrix(tr);
GL_SelectTexture(GL_TEXTURE4_ARB);
@ -564,7 +552,7 @@ void NV3x_EnableBumpShader(const transform_t *tr, const lightobject_t *lo,
glScalef(1.0f/(currentshadowlight->radiusv[0]),
1.0f/(currentshadowlight->radiusv[1]),
1.0f/(currentshadowlight->radiusv[2]));
NV3x_SetupTcMods(&currentshadowlight->shader->stages[0]);
SH_SetupTcMods(&currentshadowlight->shader->stages[0]);
GL_SetupCubeMapMatrix(tr);
GL_SelectTexture(GL_TEXTURE4_ARB);
@ -644,76 +632,6 @@ void NV3x_DisableDeluxShader(shader_t* shader)
}
/************************
Shader utility routines
*************************/
void NV3x_SetupTcMod(tcmod_t *tc)
{
switch (tc->type)
{
case TCMOD_ROTATE:
glTranslatef(0.5,0.5,0.0);
glRotatef(realtime * tc->params[0],0,0,1);
glTranslatef(-0.5, -0.5, 0.0);
break;
case TCMOD_SCROLL:
glTranslatef(realtime * tc->params[0], realtime * tc->params[1], 0.0);
break;
case TCMOD_SCALE:
glScalef(tc->params[0],tc->params[1],1.0);
break;
case TCMOD_STRETCH:
//PENTA: fixme
glScalef(1.0, 1.0, 1.0);
break;
}
}
void NV3x_SetupTcMods(stage_t *s)
{
int i;
for (i = 0; i < s->numtcmods; i++)
NV3x_SetupTcMod(&s->tcmods[i]);
}
void NV3x_SetupSimpleStage(stage_t *s)
{
tcmod_t *tc;
int i;
if (s->type != STAGE_SIMPLE)
{
Con_Printf("Non simple stage, in simple stage list");
return;
}
glMatrixMode(GL_TEXTURE);
glPushMatrix();
for (i=0; i<s->numtcmods; i++)
{
NV3x_SetupTcMod(&s->tcmods[i]);
}
if (s->src_blend > -1)
{
glBlendFunc(s->src_blend, s->dst_blend);
glEnable(GL_BLEND);
}
if (s->alphatresh > 0)
{
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, s->alphatresh);
}
if ((s->numtextures > 0) && (s->texture[0]))
GL_BindAdvanced(s->texture[0]);
}
/************************
@ -807,7 +725,7 @@ void NV3x_drawTriangleListBase (vertexdef_t *verts, int *indecies,
for ( i = 0; i < shader->numstages; i++)
{
NV3x_SetupSimpleStage(&shader->stages[i]);
SH_SetupSimpleStage(&shader->stages[i]);
glDrawElements(GL_TRIANGLES,numIndecies,GL_UNSIGNED_INT,indecies);
glPopMatrix();
}
@ -1160,7 +1078,7 @@ void NV3x_drawSurfaceListBase (vertexdef_t* verts, msurface_t** surfs,
for (i = 0; i < shader->numstages; i++)
{
NV3x_SetupSimpleStage(&shader->stages[i]);
SH_SetupSimpleStage(&shader->stages[i]);
NV3x_sendSurfacesBase(surfs, numSurfaces, false);
glPopMatrix();
}

View file

@ -33,7 +33,7 @@ qcardtype gl_cardtype = GENERIC;
qboolean gl_vbo = false; //PENTA: vertex buffer object is available
qboolean gl_texcomp = false; // JP: texture compression available
qboolean gl_mirroronce = false; //GL_ATI_texture_mirror_once extension is available
int gl_twosidedstencil = 0; // none
//void (*qglColorTableEXT) (int, int, int, int, int, const void*);
//void (*qgl3DfxSetPaletteEXT) (GLuint *);
@ -46,6 +46,12 @@ GL3DFXSETPALETTEEXTPFN qgl3DfxSetPaletteEXT;
PFNBLENDCOLORPROC qglBlendColorEXT;
// EXT_stencil_two_side
PFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
// ATI_separate_stencil
PFNGLSTENCILOPSEPARATEATIPROC qglStencilOpSeparateATI;
PFNGLSTENCILFUNCSEPARATEATIPROC qglStencilFuncSeparateATI;
//int texture_mode = GL_NEAREST;
@ -449,6 +455,26 @@ void CheckMirrorOnce(void)
}
}
void CheckTwoSidedStencil(void)
{
if (COM_CheckParm ("-notwosidedstencil"))
return;
if (strstr(gl_extensions, "GL_EXT_stencil_two_side"))
{
SAFE_GET_PROC( qglActiveStencilFaceEXT, PFNGLACTIVESTENCILFACEEXTPROC, "glActiveStencilFaceEXT");
gl_twosidedstencil = 1;
Con_Printf("Using EXT_stencil_two_side\n");
}
else if (strstr(gl_extensions, "GL_ATI_separate_stencil"))
{
SAFE_GET_PROC( qglStencilOpSeparateATI, PFNGLSTENCILOPSEPARATEATIPROC, "glStencilOpSeparateATI");
SAFE_GET_PROC( qglStencilFuncSeparateATI, PFNGLSTENCILFUNCSEPARATEATIPROC, "glStencilFuncSeparateATI");
gl_twosidedstencil = 2;
Con_Printf("Using ATI_separate_stencil\n");
}
}
static int supportedTmu;
/*
===============
@ -514,6 +540,8 @@ void GL_Init (void)
CheckOcclusionTest();
Con_Printf ("Checking MO\n");
CheckMirrorOnce();
Con_Printf ("Checking two-sided stencil\n");
CheckTwoSidedStencil();
//if something goes wrong here throw an sys_error as we don't want to end up
//having invalid function pointers called...

View file

@ -178,9 +178,6 @@ typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param);
extern PFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
extern PFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
#define GL_INCR_WRAP_EXT 0x8507
#define GL_DECR_WRAP_EXT 0x8508
#define MIN_PLAYER_MIRROR 48 //max size of player bounding box
@ -648,45 +645,51 @@ R_DrawAliasShadowVolume
void R_DrawAliasSurfaceShadowVolume (aliashdr_t *paliashdr, aliasframeinstant_t *aliasframeinstant)
{
if (paliashdr->shader->flags & SURF_NOSHADOW)
return;
if (paliashdr->shader->flags & SURF_NOSHADOW)
return;
#if 1
switch(gl_twosidedstencil)
{
case 0:
//
//Pass 1 increase
//
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
//
// Second Pass. Decrease Stencil Value In The Shadow
//
glCullFace(GL_FRONT);
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
glCullFace(GL_BACK);
R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
#else
glDisable(GL_CULL_FACE);
glCullFace(GL_FRONT_AND_BACK);
checkerror();
break;
case 1:
// EXT_stencil_two_side
glDisable(GL_CULL_FACE);
qglActiveStencilFaceEXT(GL_BACK);
glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
checkerror();
qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
checkerror();
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
checkerror();
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
checkerror();
glStencilFunc(GL_ALWAYS, 0, ~0);
qglActiveStencilFaceEXT(GL_FRONT);
glStencilOp(GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, ~0);
R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
#endif
glEnable(GL_CULL_FACE);
break;
case 2:
// ATI_separate_stencil
glDisable(GL_CULL_FACE);
glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
glEnable(GL_CULL_FACE);
break;
}
}
@ -1799,23 +1802,6 @@ void pentaGlFrustum( GLdouble xmin, GLdouble xmax, GLdouble ymin, GLdouble ymax,
glLoadMatrixd(&p[0][0]);
}
void MYgluPerspective( GLdouble fovy, GLdouble aspect,
GLdouble zNear, GLdouble zFar )
{
/*
<AWE> Unused. Can be removed.
GLdouble xmin, xmax, ymin, ymax;
ymax = zNear * tan (fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
pentaGlFrustum( xmin, xmax, ymin, ymax, zNear);
*/
pentaGlPerspective(fovy * M_PI / 360.0, aspect, zNear);
}
/*
PENTA:
@ -1986,7 +1972,7 @@ void R_SetupGL (void)
//PENTA: decreased zfar from 4096 to reduce z-fighting on alias models
// is this ok for quake or do we need to be able to look that far??
// seems to work, I incr. znear to 5 instead of 4
MYgluPerspective (2.0 *atan((GLdouble) r_refdef.vrect.height / (GLdouble) r_refdef.vrect.width) * 180.0 / M_PI /* r_refdef.fov_y */, screenaspect, 5.0, 2048.0);
pentaGlPerspective (atan((GLdouble) r_refdef.vrect.height / (GLdouble) r_refdef.vrect.width), screenaspect, 5.0);
if (mirror || glare)
{
@ -2152,10 +2138,14 @@ void R_RenderScene (void)
R_MarkEntitiesOnList();
//Shadow casting is on by default
if (l->castShadow) {
//Calculate the shadow volume (does nothing when static)
R_ConstructShadowVolume(l);
#if 1
if (l->castShadow)
{
//Calculate the shadow volume (does nothing when static)
R_ConstructShadowVolume(l);
switch(gl_twosidedstencil)
{
case 0:
//Pass 1 increase
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
@ -2176,39 +2166,52 @@ void R_RenderScene (void)
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
break;
case 1:
// EXT_stencil_two_side
glDisable(GL_CULL_FACE);
qglActiveStencilFaceEXT(GL_BACK);
glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, ~0);
qglActiveStencilFaceEXT(GL_FRONT);
glStencilOp(GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, ~0);
if (sh_worldshadows.value) R_DrawShadowVolume(l);
#else
// glCullFace(GL_FRONT_AND_BACK);
glDisable(GL_CULL_FACE);
checkerror();
glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
checkerror();
qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
checkerror();
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
checkerror();
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
checkerror();
//PENTA: we could do the same thing for brushes as for aliasses
//Pass 1 increase
if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
glEnable(GL_CULL_FACE);
qglActiveStencilFaceEXT(GL_FRONT_AND_BACK);
break;
case 2:
// ATI_separate_stencil
glDisable(GL_CULL_FACE);
glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
if (sh_worldshadows.value) R_DrawShadowVolume(l);
//PENTA: we could do the same thing for brushes as for aliasses
//PENTA: we could do the same thing for brushes as for aliasses
//Pass 1 increase
if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
glEnable(GL_CULL_FACE);
break;
}
if (sh_entityshadows.value)
R_DrawEntitiesShadowVolumes(mod_alias);
glEnable(GL_CULL_FACE);
#endif
if (sh_entityshadows.value)
R_DrawEntitiesShadowVolumes(mod_alias);
if (sh_meshshadows.value)
StencilMeshVolumes();
if (sh_meshshadows.value)
StencilMeshVolumes();
//Reenable drawing
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDepthFunc(GL_LEQUAL);
glStencilFunc(GL_EQUAL, 0, 0xffffffff);
//Reenable drawing
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDepthFunc(GL_LEQUAL);
glStencilFunc(GL_EQUAL, 0, 0xffffffff);
}

View file

@ -1967,13 +1967,51 @@ void StencilMeshVolume(mesh_t *mesh) {
glCullFace(GL_BACK);
}
void StencilMeshVolumes() {
void StencilMeshVolume2(mesh_t *mesh)
{
if (mesh->shader->shader->flags & SURF_NOSHADOW) return;
SetupMeshToLightVisibility(currentshadowlight, mesh);
DrawMeshVolume(mesh);
}
int i;
for (i=0; i<currentshadowlight->numlightcmdsmesh-1; i++) {
StencilMeshVolume((mesh_t *)currentshadowlight->lightCmdsMesh[i].asVoid);
}
void StencilMeshVolumes()
{
int i;
switch(gl_twosidedstencil)
{
case 0:
for (i=0; i<currentshadowlight->numlightcmdsmesh-1; i++)
StencilMeshVolume((mesh_t *)currentshadowlight->lightCmdsMesh[i].asVoid);
break;
case 1:
// EXT_stencil_two_side
glDisable(GL_CULL_FACE);
qglActiveStencilFaceEXT(GL_BACK);
glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, ~0);
qglActiveStencilFaceEXT(GL_FRONT);
glStencilOp(GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, ~0);
for (i=0; i<currentshadowlight->numlightcmdsmesh-1; i++)
StencilMeshVolume2((mesh_t *)currentshadowlight->lightCmdsMesh[i].asVoid);
glEnable(GL_CULL_FACE);
qglActiveStencilFaceEXT(GL_FRONT_AND_BACK);
break;
case 2:
// ATI_separate_stencil
glDisable(GL_CULL_FACE);
glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
for (i=0; i<currentshadowlight->numlightcmdsmesh-1; i++)
StencilMeshVolume2((mesh_t *)currentshadowlight->lightCmdsMesh[i].asVoid);
glEnable(GL_CULL_FACE);
break;
}
}

View file

@ -485,6 +485,22 @@ extern int occlusion_cut_meshes;
extern int occlusion_cut_entities;
extern int occlusion_cut_lights;
// EXT_stencil_two_side
#define GL_INCR_WRAP_EXT 0x8507
#define GL_DECR_WRAP_EXT 0x8508
#ifndef GL_EXT_stencil_two_side
#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
#define GL_ACTIVE_STENCIL_FACE_EXT 0x8911
#endif
#ifndef GL_EXT_stencil_two_side
#define GL_EXT_stencil_two_side 1
typedef void (APIENTRY * PFNGLACTIVESTENCILFACEEXTPROC) (GLenum face);
#endif
extern PFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
// ATI_separate_stencil
#define GL_STENCIL_BACK_FUNC_ATI 0x8800
#define GL_STENCIL_BACK_FAIL_ATI 0x8801
#define GL_STENCIL_BACK_PASS_DEPTH_FAIL_ATI 0x8802
@ -1059,17 +1075,18 @@ extern PFNGLGETBUFFERPOINTERVARBPROC qglGetBufferPointervARB;
extern qboolean gl_mtexable;
extern qboolean gl_texturefilteranisotropic; // <AWE> true if anisotropic texture filtering available.
extern int gl_twosidedstencil;
typedef enum
{
GENERIC = 0,
GEFORCE,
GEFORCE3,
RADEON,
PARHELIA,
ARB,
NV3x,
GL2
GENERIC = 0,
GEFORCE,
GEFORCE3,
RADEON,
PARHELIA,
ARB,
NV3x,
GL2
} qcardtype;
extern qcardtype gl_cardtype;