Implement depth textures and shadow mapping in DirectX 9 renderer
(at long last)
This commit is contained in:
parent
a819e9055b
commit
fb317e3b7a
|
|
@ -2647,6 +2647,18 @@ reset() {
|
|||
}
|
||||
}
|
||||
|
||||
_supports_depth_stencil = ((_screen->_supported_tex_formats_mask & D24S8_FLAG) != 0);
|
||||
_supports_depth_texture = _supports_depth_stencil ||
|
||||
(_screen->_supported_tex_formats_mask & D16_FLAG) != 0 ||
|
||||
(_screen->_supported_tex_formats_mask & D32_FLAG) != 0 ||
|
||||
(_screen->_supported_tex_formats_mask & D24X8_FLAG) != 0;
|
||||
|
||||
// In DirectX 9, all built-in depth formats use shadow map filtering. Some
|
||||
// drivers (GeForce 8000+, Radeon HD 4000+, Intel G45+) expose a FourCC
|
||||
// format called "INTZ" that allows access to the actual depth. We don't
|
||||
// have a flag to indicate this, though.
|
||||
_supports_shadow_filter = _supports_depth_texture;
|
||||
|
||||
// check if compressed textures are supported
|
||||
#define CHECK_FOR_DXTVERSION(num) \
|
||||
if (_screen->_supported_tex_formats_mask & DXT##num##_FLAG) {\
|
||||
|
|
|
|||
|
|
@ -119,6 +119,8 @@ create_texture(DXScreenData &scrn) {
|
|||
int num_alpha_bits; // number of alpha bits in texture pixfmt
|
||||
D3DFORMAT target_pixel_format = D3DFMT_UNKNOWN;
|
||||
bool needs_luminance = false;
|
||||
bool needs_depth = false;
|
||||
bool needs_stencil = false;
|
||||
bool compress_texture = false;
|
||||
|
||||
Texture *tex = get_texture();
|
||||
|
|
@ -190,53 +192,75 @@ create_texture(DXScreenData &scrn) {
|
|||
DWORD target_bpp = get_bits_per_pixel(tex->get_format(), &num_alpha_bits);
|
||||
DWORD num_color_channels = tex->get_num_components();
|
||||
|
||||
// printf ("format = %d \n", tex->get_format());
|
||||
// printf ("target_bpp %d, num_color_channels %d num_alpha_bits %d \n", target_bpp, num_color_channels, num_alpha_bits);
|
||||
|
||||
//PRINT_REFCNT(dxgsg9, scrn._d3d9);
|
||||
|
||||
if ((tex->get_format() == Texture::F_luminance_alpha)||
|
||||
(tex->get_format() == Texture::F_luminance_alphamask) ||
|
||||
(tex->get_format() == Texture::F_luminance) ||
|
||||
(tex->get_format() == Texture::F_sluminance_alpha) ||
|
||||
(tex->get_format() == Texture::F_sluminance)) {
|
||||
needs_luminance = true;
|
||||
}
|
||||
|
||||
if (num_alpha_bits > 0) {
|
||||
if (num_color_channels == 3) {
|
||||
dxgsg9_cat.error()
|
||||
<< "texture " << tex->get_name()
|
||||
<< " has no inherent alpha channel, but alpha format is requested!\n";
|
||||
}
|
||||
}
|
||||
|
||||
_d3d_format = D3DFMT_UNKNOWN;
|
||||
|
||||
// figure out what 'D3DFMT' the Texture is in, so D3DXLoadSurfFromMem knows how to perform copy
|
||||
|
||||
switch (num_color_channels) {
|
||||
case 1:
|
||||
if (num_alpha_bits > 0) {
|
||||
_d3d_format = D3DFMT_A8;
|
||||
} else if (needs_luminance) {
|
||||
_d3d_format = D3DFMT_L8;
|
||||
}
|
||||
switch (tex->get_format()) {
|
||||
case Texture::F_depth_stencil:
|
||||
_d3d_format = D3DFMT_D24S8;
|
||||
needs_depth = true;
|
||||
needs_stencil = true;
|
||||
break;
|
||||
case 2:
|
||||
nassertr(needs_luminance && (num_alpha_bits > 0), false);
|
||||
|
||||
case Texture::F_depth_component:
|
||||
case Texture::F_depth_component16:
|
||||
_d3d_format = D3DFMT_D16;
|
||||
needs_depth = true;
|
||||
break;
|
||||
|
||||
case Texture::F_depth_component24:
|
||||
_d3d_format = D3DFMT_D24X8;
|
||||
needs_depth = true;
|
||||
break;
|
||||
|
||||
case Texture::F_depth_component32:
|
||||
_d3d_format = D3DFMT_D32;
|
||||
needs_depth = true;
|
||||
break;
|
||||
|
||||
case Texture::F_luminance:
|
||||
case Texture::F_sluminance:
|
||||
_d3d_format = D3DFMT_L8;
|
||||
needs_luminance = true;
|
||||
break;
|
||||
|
||||
case Texture::F_luminance_alpha:
|
||||
case Texture::F_luminance_alphamask:
|
||||
case Texture::F_sluminance_alpha:
|
||||
_d3d_format = D3DFMT_A8L8;
|
||||
needs_luminance = true;
|
||||
break;
|
||||
case 3:
|
||||
_d3d_format = D3DFMT_R8G8B8;
|
||||
break;
|
||||
case 4:
|
||||
_d3d_format = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
}
|
||||
|
||||
// make sure we handled all the possible cases
|
||||
nassertr(_d3d_format != D3DFMT_UNKNOWN, false);
|
||||
default:
|
||||
if (num_alpha_bits > 0) {
|
||||
if (num_color_channels == 3) {
|
||||
dxgsg9_cat.error()
|
||||
<< "texture " << tex->get_name()
|
||||
<< " has no inherent alpha channel, but alpha format is requested!\n";
|
||||
}
|
||||
}
|
||||
|
||||
_d3d_format = D3DFMT_UNKNOWN;
|
||||
|
||||
switch (num_color_channels) {
|
||||
case 1:
|
||||
if (num_alpha_bits > 0) {
|
||||
_d3d_format = D3DFMT_A8;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
nassertr(false && (num_alpha_bits > 0), false);
|
||||
_d3d_format = D3DFMT_A8L8;
|
||||
break;
|
||||
case 3:
|
||||
_d3d_format = D3DFMT_R8G8B8;
|
||||
break;
|
||||
case 4:
|
||||
_d3d_format = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
}
|
||||
|
||||
// make sure we handled all the possible cases
|
||||
nassertr(_d3d_format != D3DFMT_UNKNOWN, false);
|
||||
}
|
||||
|
||||
DWORD target_width = orig_width;
|
||||
DWORD target_height = orig_height;
|
||||
|
|
@ -447,6 +471,14 @@ create_texture(DXScreenData &scrn) {
|
|||
goto found_matching_format;
|
||||
|
||||
case 32:
|
||||
if (needs_depth) {
|
||||
nassertr(num_alpha_bits == 0, false);
|
||||
nassertr(num_color_channels == 1, false);
|
||||
|
||||
CHECK_FOR_FMT(D32);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!((num_color_channels == 3) || (num_color_channels == 4)))
|
||||
break; //bail
|
||||
|
||||
|
|
@ -494,25 +526,78 @@ create_texture(DXScreenData &scrn) {
|
|||
break;
|
||||
|
||||
case 24:
|
||||
nassertr(num_color_channels == 3, false);
|
||||
if (needs_depth) {
|
||||
nassertr(num_alpha_bits == 0, false);
|
||||
nassertr(num_color_channels == 1, false);
|
||||
|
||||
CHECK_FOR_FMT(R8G8B8);
|
||||
// In DirectX 9, all built-in depth formats use shadow map filtering.
|
||||
// Some drivers (GeForce 8000+, Radeon HD 4000+, Intel G45+) expose a
|
||||
// FourCC format called "INTZ" that allows access to the actual depth.
|
||||
if (tex->get_minfilter() == Texture::FT_shadow) {
|
||||
if (needs_stencil) {
|
||||
CHECK_FOR_FMT(D24S8);
|
||||
}
|
||||
CHECK_FOR_FMT(D24X8);
|
||||
CHECK_FOR_FMT(D32);
|
||||
CHECK_FOR_FMT(D16);
|
||||
} else {
|
||||
if (scrn._supported_tex_formats_mask & INTZ_FLAG) {
|
||||
target_pixel_format = (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z');
|
||||
goto found_matching_format;
|
||||
}
|
||||
|
||||
// no 24-bit fmt. look for 32 bit fmt (note: this is
|
||||
// memory-hogging choice instead I could look for
|
||||
// memory-conserving 16-bit fmt).
|
||||
// We fall back to a depth format. Chances are that it is going to
|
||||
// be used for shadow mapping, in which case the depth comparison
|
||||
// will probably still result in a useful value.
|
||||
CHECK_FOR_FMT(D24X8);
|
||||
}
|
||||
} else {
|
||||
nassertr(num_color_channels == 3, false);
|
||||
|
||||
CHECK_FOR_FMT(X8R8G8B8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
CHECK_FOR_FMT(R8G8B8);
|
||||
|
||||
// no 24-bit or 32 fmt. look for 16 bit fmt (higher res 565 1st)
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
// no 24-bit fmt. look for 32 bit fmt (note: this is
|
||||
// memory-hogging choice instead I could look for
|
||||
// memory-conserving 16-bit fmt).
|
||||
|
||||
CHECK_FOR_FMT(X8R8G8B8);
|
||||
CHECK_FOR_FMT(A8R8G8B8);
|
||||
|
||||
// no 24-bit or 32 fmt. look for 16 bit fmt (higher res 565 1st)
|
||||
CHECK_FOR_FMT(R5G6B5);
|
||||
CHECK_FOR_FMT(X1R5G5B5);
|
||||
CHECK_FOR_FMT(A1R5G5B5);
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
if (needs_luminance) {
|
||||
if (needs_depth) {
|
||||
nassertr(num_alpha_bits == 0, false);
|
||||
nassertr(num_color_channels == 1, false);
|
||||
|
||||
// In DirectX 9, all built-in depth formats use shadow map filtering.
|
||||
// Some drivers (GeForce 8000+, Radeon HD 4000+, Intel G45+) expose a
|
||||
// FourCC format called "INTZ" that allows access to the actual depth.
|
||||
if (tex->get_minfilter() == Texture::FT_shadow) {
|
||||
if (needs_stencil) {
|
||||
CHECK_FOR_FMT(D24S8);
|
||||
}
|
||||
CHECK_FOR_FMT(D16);
|
||||
CHECK_FOR_FMT(D24X8);
|
||||
CHECK_FOR_FMT(D32);
|
||||
} else {
|
||||
if (scrn._supported_tex_formats_mask & INTZ_FLAG) {
|
||||
target_pixel_format = (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z');
|
||||
goto found_matching_format;
|
||||
}
|
||||
|
||||
// We fall back to a depth format. Chances are that it is going to
|
||||
// be used for shadow mapping, in which case the depth comparison
|
||||
// will probably still result in a useful value.
|
||||
CHECK_FOR_FMT(D24X8);
|
||||
}
|
||||
|
||||
} else if (needs_luminance) {
|
||||
nassertr(num_alpha_bits > 0, false);
|
||||
nassertr(num_color_channels == 2, false);
|
||||
|
||||
|
|
@ -613,11 +698,13 @@ create_texture(DXScreenData &scrn) {
|
|||
// Instead of creating a texture with the found format, we will
|
||||
// need to make one that exactly matches the framebuffer's
|
||||
// format. Look up what that format is.
|
||||
DWORD render_target_index;
|
||||
IDirect3DSurface9 *render_target;
|
||||
|
||||
render_target_index = 0;
|
||||
hr = scrn._d3d_device->GetRenderTarget(render_target_index, &render_target);
|
||||
if (needs_depth) {
|
||||
hr = scrn._d3d_device->GetDepthStencilSurface(&render_target);
|
||||
} else {
|
||||
hr = scrn._d3d_device->GetRenderTarget(0, &render_target);
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
dxgsg9_cat.error()
|
||||
<< "GetRenderTgt failed in create_texture: " << D3DERRORSTRING(hr);
|
||||
|
|
@ -628,7 +715,8 @@ create_texture(DXScreenData &scrn) {
|
|||
dxgsg9_cat.error()
|
||||
<< "GetDesc failed in create_texture: " << D3DERRORSTRING(hr);
|
||||
} else {
|
||||
if (target_pixel_format != surface_desc.Format) {
|
||||
if (target_pixel_format != surface_desc.Format &&
|
||||
target_pixel_format != MAKEFOURCC('I', 'N', 'T', 'Z')) {
|
||||
if (dxgsg9_cat.is_debug()) {
|
||||
dxgsg9_cat.debug()
|
||||
<< "Chose format " << D3DFormatStr(surface_desc.Format)
|
||||
|
|
@ -786,10 +874,14 @@ create_texture(DXScreenData &scrn) {
|
|||
_is_render_target = true;
|
||||
|
||||
pool = D3DPOOL_DEFAULT;
|
||||
usage = D3DUSAGE_RENDERTARGET;
|
||||
if (target_bpp <= 32 ) {
|
||||
target_pixel_format = scrn._render_to_texture_d3d_format;
|
||||
if (needs_depth) {
|
||||
usage = D3DUSAGE_DEPTHSTENCIL;
|
||||
} else {
|
||||
usage = D3DUSAGE_RENDERTARGET;
|
||||
}
|
||||
//if (target_bpp <= 32) {
|
||||
// target_pixel_format = scrn._render_to_texture_d3d_format;
|
||||
//}
|
||||
|
||||
dxgsg9_cat.debug ()
|
||||
<< "*** RENDER TO TEXTURE ***: format "
|
||||
|
|
@ -1126,6 +1218,22 @@ extract_texture_data(DXScreenData &screen) {
|
|||
format = Texture::F_luminance_alpha;
|
||||
break;
|
||||
|
||||
case D3DFMT_D24S8:
|
||||
format = Texture::F_depth_stencil;
|
||||
break;
|
||||
|
||||
case D3DFMT_D16:
|
||||
format = Texture::F_depth_component16;
|
||||
break;
|
||||
|
||||
case D3DFMT_D24X8:
|
||||
format = Texture::F_depth_component24;
|
||||
break;
|
||||
|
||||
case D3DFMT_D32:
|
||||
format = Texture::F_depth_component32;
|
||||
break;
|
||||
|
||||
case D3DFMT_DXT1:
|
||||
compression = Texture::CM_dxt1;
|
||||
div = 4;
|
||||
|
|
@ -2159,8 +2267,12 @@ get_bits_per_pixel(Texture::Format format, int *alphbits) {
|
|||
*alphbits = 1;
|
||||
return 16;
|
||||
case Texture::F_depth_component:
|
||||
case Texture::F_depth_component16:
|
||||
return 16;
|
||||
case Texture::F_depth_stencil:
|
||||
case Texture::F_depth_component24:
|
||||
return 24;
|
||||
case Texture::F_depth_component32:
|
||||
return 32;
|
||||
case Texture::F_rgb5:
|
||||
return 16;
|
||||
|
|
@ -2233,6 +2345,8 @@ d3d_format_to_bytes_per_pixel (D3DFORMAT format)
|
|||
case D3DFMT_A8L8:
|
||||
case D3DFMT_A8R3G3B2:
|
||||
case D3DFMT_X4R4G4B4:
|
||||
case D3DFMT_D16:
|
||||
case (D3DFORMAT)MAKEFOURCC('D', 'F', '1', '6'):
|
||||
bytes_per_pixel = 2.0f;
|
||||
break;
|
||||
|
||||
|
|
@ -2251,6 +2365,11 @@ d3d_format_to_bytes_per_pixel (D3DFORMAT format)
|
|||
case D3DFMT_X8B8G8R8:
|
||||
case D3DFMT_G16R16:
|
||||
case D3DFMT_A2R10G10B10:
|
||||
case D3DFMT_D24X8:
|
||||
case D3DFMT_D24S8:
|
||||
case D3DFMT_D32:
|
||||
case (D3DFORMAT)MAKEFOURCC('D', 'F', '2', '4'):
|
||||
case (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z'):
|
||||
bytes_per_pixel = 4.0f;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -165,11 +165,11 @@ typedef enum {
|
|||
L8_FLAG = FLG(15),
|
||||
A8L8_FLAG = FLG(16),
|
||||
A4L4_FLAG = FLG(17),
|
||||
V8U8_FLAG = FLG(18),
|
||||
L6V5U5_FLAG = FLG(19),
|
||||
X8L8V8U8_FLAG = FLG(20),
|
||||
Q8W8V8U8_FLAG = FLG(21),
|
||||
V16U16_FLAG = FLG(22),
|
||||
D16_FLAG = FLG(18),
|
||||
D24X8_FLAG = FLG(19),
|
||||
D24S8_FLAG = FLG(20),
|
||||
D32_FLAG = FLG(21),
|
||||
INTZ_FLAG = FLG(22),
|
||||
W11V11U10_FLAG = FLG(23),
|
||||
A2W10V10U10_FLAG = FLG(24),
|
||||
UYVY_FLAG = FLG(25),
|
||||
|
|
|
|||
|
|
@ -296,9 +296,6 @@ rebuild_bitplanes() {
|
|||
|
||||
// Find the color and depth textures. Either may be present,
|
||||
// or neither.
|
||||
//
|
||||
// NOTE: Currently, depth-stencil textures are not implemented,
|
||||
// but since it's coming soon, we're structuring for it.
|
||||
|
||||
int color_tex_index = -1;
|
||||
int depth_tex_index = -1;
|
||||
|
|
@ -315,6 +312,11 @@ rebuild_bitplanes() {
|
|||
color_tex_index = i;
|
||||
break;
|
||||
|
||||
case RTP_depth:
|
||||
case RTP_depth_stencil:
|
||||
depth_tex_index = i;
|
||||
break;
|
||||
|
||||
case RTP_aux_rgba_0:
|
||||
case RTP_aux_rgba_1:
|
||||
case RTP_aux_rgba_2:
|
||||
|
|
|
|||
|
|
@ -890,11 +890,11 @@ void Init_D3DFORMAT_map() {
|
|||
INSERT_ELEM(L8);
|
||||
INSERT_ELEM(A8L8);
|
||||
INSERT_ELEM(A4L4);
|
||||
INSERT_ELEM(V8U8);
|
||||
INSERT_ELEM(L6V5U5);
|
||||
INSERT_ELEM(X8L8V8U8);
|
||||
INSERT_ELEM(Q8W8V8U8);
|
||||
INSERT_ELEM(V16U16);
|
||||
INSERT_ELEM(D16);
|
||||
INSERT_ELEM(D24X8);
|
||||
INSERT_ELEM(D24S8);
|
||||
INSERT_ELEM(D32);
|
||||
g_D3DFORMATmap[INTZ_FLAG] = (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z');
|
||||
// NOT IN DX9
|
||||
// INSERT_ELEM(W11V11U10);
|
||||
INSERT_ELEM(A2W10V10U10);
|
||||
|
|
|
|||
Loading…
Reference in New Issue