qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
+ if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
if (usewaterfbo)
{
if (r_fb.water.depthtexture == NULL)
- r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
+ r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
if (p->fbo_refraction == 0)
p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
}
if (usewaterfbo)
{
if (r_fb.water.depthtexture == NULL)
- r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
+ r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
if (p->fbo_camera == 0)
p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
}
if (usewaterfbo)
{
if (r_fb.water.depthtexture == NULL)
- r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
+ r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
if (p->fbo_reflection == 0)
p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
}
if (useviewfbo)
{
// FIXME: choose depth bits based on a cvar
- r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
+ r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false, vid.support.ext_packed_depth_stencil);
r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
#ifndef USE_GLES2
// GLES2 devices rarely support depth textures, so we actually use a renderbuffer there
static textypeinfo_t textype_shadowmap16 = {"shadowmap16", TEXTYPE_SHADOWMAP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
static textypeinfo_t textype_shadowmap24 = {"shadowmap24", TEXTYPE_SHADOWMAP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
+static textypeinfo_t textype_shadowmap24s8 = {"shadowmap24", TEXTYPE_SHADOWMAP_STENCIL, 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F, 8, 8, 8.0f, GL_RGBA , GL_RGBA , GL_FLOAT };
static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F, 16, 16, 16.0f, GL_RGBA , GL_RGBA , GL_FLOAT };
#else
// framebuffer texture formats
static textypeinfo_t textype_shadowmap16 = {"shadowmap16", TEXTYPE_SHADOWMAP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT};
-static textypeinfo_t textype_shadowmap24 = {"shadowmap24", TEXTYPE_SHADOWMAP , 4, 4, 4.0f, GL_DEPTH_COMPONENT24_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
+static textypeinfo_t textype_shadowmap24 = {"shadowmap24", TEXTYPE_SHADOWMAP , 4, 4, 4.0f, GL_DEPTH_COMPONENT , GL_DEPTH_COMPONENT, GL_UNSIGNED_INT };
+static textypeinfo_t textype_shadowmap24s8 = {"shadowmap24", TEXTYPE_SHADOWMAP_STENCIL, 4, 4, 4.0f, GL_DEPTH24_STENCIL8_EXT , GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT};
static textypeinfo_t textype_colorbuffer = {"colorbuffer", TEXTYPE_COLORBUFFER , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE };
static textypeinfo_t textype_colorbuffer16f = {"colorbuffer16f", TEXTYPE_COLORBUFFER16F, 8, 8, 8.0f, GL_RGBA16F_ARB , GL_RGBA , GL_FLOAT };
static textypeinfo_t textype_colorbuffer32f = {"colorbuffer32f", TEXTYPE_COLORBUFFER32F, 16, 16, 16.0f, GL_RGBA32F_ARB , GL_RGBA , GL_FLOAT };
case TEXTYPE_BGRA: return ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra);
case TEXTYPE_ALPHA: return &textype_alpha;
case TEXTYPE_SHADOWMAP: return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
+ case TEXTYPE_SHADOWMAP_STENCIL: return &textype_shadowmap24s8;
case TEXTYPE_COLORBUFFER: return &textype_colorbuffer;
case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f;
case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f;
case TEXTYPE_BGRA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_bgra_alpha_compress : &textype_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra);
case TEXTYPE_ALPHA: return &textype_alpha;
case TEXTYPE_SHADOWMAP: return (flags & TEXF_LOWPRECISION) ? &textype_shadowmap16 : &textype_shadowmap24;
+ case TEXTYPE_SHADOWMAP_STENCIL: return &textype_shadowmap24s8;
case TEXTYPE_COLORBUFFER: return &textype_colorbuffer;
case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f;
case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f;
}
#ifndef USE_GLES2
- if (textype == TEXTYPE_SHADOWMAP)
+ if (textype == TEXTYPE_SHADOWMAP || TEXTYPE_SHADOWMAP_STENCIL)
{
if (vid.support.arb_shadow)
{
}
break;
case TEXTYPE_SHADOWMAP:
+ case TEXTYPE_SHADOWMAP_STENCIL:
break;
case TEXTYPE_DXT1:
case TEXTYPE_SRGB_DXT1:
case TEXTYPE_COLORBUFFER: d3dformat = D3DFMT_A8R8G8B8;break;
case TEXTYPE_COLORBUFFER16F: d3dformat = D3DFMT_A16B16G16R16F;break;
case TEXTYPE_COLORBUFFER32F: d3dformat = D3DFMT_A32B32G32R32F;break;
- case TEXTYPE_SHADOWMAP: d3dformat = D3DFMT_D16;d3dusage = D3DUSAGE_DEPTHSTENCIL;break; // note: can not use D3DUSAGE_RENDERTARGET here
+ case TEXTYPE_SHADOWMAP: d3dformat = D3DFMT_D24X8;d3dusage = D3DUSAGE_DEPTHSTENCIL;break; // note: can not use D3DUSAGE_RENDERTARGET here
+ case TEXTYPE_SHADOWMAP_STENCIL: d3dformat = D3DFMT_D24S8;d3dusage = D3DUSAGE_DEPTHSTENCIL;break; // note: can not use D3DUSAGE_RENDERTARGET here
case TEXTYPE_ALPHA: d3dformat = D3DFMT_A8;break;
default: d3dformat = D3DFMT_A8R8G8B8;Sys_Error("R_LoadTexture: unsupported texture type %i when picking D3DFMT", (int)textype);break;
}
glt->d3dformat = d3dformat;
glt->d3dusage = d3dusage;
glt->d3dpool = d3dpool;
- glt->d3disdepthsurface = textype == TEXTYPE_SHADOWMAP;
+ glt->d3disdepthsurface = (textype == TEXTYPE_SHADOWMAP || textype == TEXTYPE_SHADOWMAP_STENCIL);
if (glt->d3disdepthsurface)
{
if (FAILED(d3dresult = IDirect3DDevice9_CreateDepthStencilSurface(vid_d3d9dev, glt->tilewidth, glt->tileheight, (D3DFORMAT)glt->d3dformat, D3DMULTISAMPLE_NONE, 0, false, (IDirect3DSurface9 **)&glt->d3dtexture, NULL)))
case TEXTYPE_COLORBUFFER16F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA16F;break;
case TEXTYPE_COLORBUFFER32F: tflags = DPSOFTRAST_TEXTURE_FORMAT_RGBA32F;break;
case TEXTYPE_SHADOWMAP: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
+ case TEXTYPE_SHADOWMAP_STENCIL: tflags = DPSOFTRAST_TEXTURE_FORMAT_DEPTH;break;
case TEXTYPE_ALPHA: tflags = DPSOFTRAST_TEXTURE_FORMAT_ALPHA8;break;
default: Sys_Error("R_LoadTexture: unsupported texture type %i when picking DPSOFTRAST_TEXTURE_FLAGS", (int)textype);
}
return flags;
}
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter)
+rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter, qboolean stencil)
{
- return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
+ return R_SetupTexture(rtexturepool, identifier, width, height, 1, 1, R_ShadowMapTextureFlags(precision, filter), -1, stencil ? TEXTYPE_SHADOWMAP_STENCIL : TEXTYPE_SHADOWMAP, GLTEXTURETYPE_2D, NULL, NULL);
}
int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipuncompressed, qboolean hasalpha)
extern void (GLAPIENTRY *qglSampleCoverageARB)(GLclampf value, GLboolean invert);
extern void (GLAPIENTRY *qglPointSize)(GLfloat size);
+
+//GL_EXT_packed_depth_stencil
+#define GL_DEPTH_STENCIL_EXT 0x84F9
+#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
+#define GL_DEPTH24_STENCIL8_EXT 0x88F0
+
#endif
#define DEBUGGL
{
case R_SHADOW_SHADOWMODE_SHADOWMAP2D:
if (r_shadow_shadowmap2dtexture) return;
- r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler);
+ r_shadow_shadowmap2dtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "shadowmap", size*2, size*(vid.support.arb_texture_non_power_of_two ? 3 : 4), r_shadow_shadowmapdepthbits, r_shadow_shadowmapsampler, false);
r_shadow_shadowmap2dcolortexture = NULL;
switch(vid.renderpath)
{
r_shadow_usingdeferredprepass = true;
r_shadow_prepass_width = vid.width;
r_shadow_prepass_height = vid.height;
- r_shadow_prepassgeometrydepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "prepassgeometrydepthmap", vid.width, vid.height, 24, false);
+ r_shadow_prepassgeometrydepthtexture = R_LoadTextureShadowMap2D(r_shadow_texturepool, "prepassgeometrydepthmap", vid.width, vid.height, 24, false, false);
switch (vid.renderpath)
{
case RENDERPATH_D3D9:
TEXTYPE_COLORBUFFER16F,
// this represents an RGBA float texture (4 32bit floats)
TEXTYPE_COLORBUFFER32F,
+ // 32bit D24S8 (24bit depth, 8bit stencil)
+ TEXTYPE_SHADOWMAP_STENCIL,
// 16bit D16 (16bit depth) or 32bit S8D24 (24bit depth, 8bit stencil unused)
TEXTYPE_SHADOWMAP
}
rtexture_t *R_LoadTexture2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
rtexture_t *R_LoadTexture3D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int depth, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
rtexture_t *R_LoadTextureCubeMap(rtexturepool_t *rtexturepool, const char *identifier, int width, const unsigned char *data, textype_t textype, int flags, int miplevel, const unsigned int *palette);
-rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter);
+rtexture_t *R_LoadTextureShadowMap2D(rtexturepool_t *rtexturepool, const char *identifier, int width, int height, int precision, qboolean filter, qboolean stencil);
rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel);
// saves a texture to a DDS file
qboolean ext_blend_subtract;
qboolean ext_draw_range_elements;
qboolean ext_framebuffer_object;
+ qboolean ext_packed_depth_stencil;
qboolean ext_stencil_two_side;
qboolean ext_texture_3d;
qboolean ext_texture_compression_s3tc;
vid.support.ext_blend_subtract = true;
vid.support.ext_draw_range_elements = true;
vid.support.ext_framebuffer_object = false;//true;
+ vid.support.ext_packed_depth_stencil = false;
vid.support.ext_stencil_two_side = false;
vid.support.ext_texture_3d = SDL_GL_ExtensionSupported("GL_OES_texture_3D");
vid.support.ext_texture_compression_s3tc = SDL_GL_ExtensionSupported("GL_EXT_texture_compression_s3tc");
vid.support.ext_blend_subtract = GL_CheckExtension("GL_EXT_blend_subtract", blendequationfuncs, "-noblendsubtract", false);
vid.support.ext_draw_range_elements = GL_CheckExtension("drawrangeelements", drawrangeelementsfuncs, "-nodrawrangeelements", true) || GL_CheckExtension("GL_EXT_draw_range_elements", drawrangeelementsextfuncs, "-nodrawrangeelements", false);
vid.support.ext_framebuffer_object = GL_CheckExtension("GL_EXT_framebuffer_object", fbofuncs, "-nofbo", false);
+ vid.support.ext_packed_depth_stencil = GL_CheckExtension("GL_EXT_packed_depth_stencil", NULL, "-nopackeddepthstencil", false);
vid.support.ext_stencil_two_side = GL_CheckExtension("GL_EXT_stencil_two_side", stenciltwosidefuncs, "-nostenciltwoside", false);
vid.support.ext_texture_3d = GL_CheckExtension("GL_EXT_texture3D", texture3dextfuncs, "-notexture3d", false);
vid.support.ext_texture_compression_s3tc = GL_CheckExtension("GL_EXT_texture_compression_s3tc", NULL, "-nos3tc", false);