mirror of https://github.com/xemu-project/xemu.git
nv2a: Implement shadow samplers
This commit is contained in:
parent
b9aef0c57c
commit
c33d96127c
|
@ -304,6 +304,8 @@ typedef struct PGRAPHState {
|
|||
|
||||
bool texture_matrix_enable[NV2A_MAX_TEXTURES];
|
||||
|
||||
enum PshShadowDepthFunc shadow_depth_func;
|
||||
|
||||
GLuint gl_framebuffer;
|
||||
|
||||
GLuint gl_display_buffer;
|
||||
|
|
|
@ -1218,6 +1218,15 @@
|
|||
# define NV097_SET_COMBINER_COLOR_OCW 0x00001E40
|
||||
# define NV097_SET_COMBINER_CONTROL 0x00001E60
|
||||
# define NV097_SET_SHADOW_ZSLOPE_THRESHOLD 0x00001E68
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC 0x00001E6C
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_NEVER 0x00000000
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_LESS 0x00000001
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_EQUAL 0x00000002
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_LEQUAL 0x00000003
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_GREATER 0x00000004
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_NOTEQUAL 0x00000005
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_GEQUAL 0x00000006
|
||||
# define NV097_SET_SHADOW_DEPTH_FUNC_ALWAYS 0x00000007
|
||||
# define NV097_SET_SHADER_STAGE_PROGRAM 0x00001E70
|
||||
# define NV097_SET_DOT_RGBMAPPING 0X00001E74
|
||||
# define NV097_SET_SHADER_OTHER_STAGE_INPUT 0x00001E78
|
||||
|
|
|
@ -219,6 +219,7 @@ typedef struct ColorFormatInfo {
|
|||
GLenum gl_format;
|
||||
GLenum gl_type;
|
||||
GLenum gl_swizzle_mask[4];
|
||||
bool depth;
|
||||
} ColorFormatInfo;
|
||||
|
||||
static const ColorFormatInfo kelvin_color_format_map[66] = {
|
||||
|
@ -300,14 +301,20 @@ static const ColorFormatInfo kelvin_color_format_map[66] = {
|
|||
{2, true, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_YB8CR8YA8CB8] =
|
||||
{2, true, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV},
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED] =
|
||||
{4, true, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8},
|
||||
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_DEPTH_Y16_FIXED] =
|
||||
{2, false, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT},
|
||||
{2, false, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
|
||||
{GL_RED, GL_ZERO, GL_ZERO, GL_ZERO}, true},
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED] =
|
||||
{4, true, GL_DEPTH_COMPONENT, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8,
|
||||
{GL_RED, GL_ONE, GL_ZERO, GL_ZERO}, true},
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FIXED] =
|
||||
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT},
|
||||
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
|
||||
{GL_RED, GL_ZERO, GL_ZERO, GL_ZERO}, true},
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FLOAT] =
|
||||
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT},
|
||||
{2, true, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT,
|
||||
{GL_RED, GL_ZERO, GL_ZERO, GL_ZERO}, true},
|
||||
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_Y16] =
|
||||
{2, true, GL_R16, GL_RED, GL_UNSIGNED_SHORT,
|
||||
{GL_RED, GL_RED, GL_RED, GL_ONE}},
|
||||
|
@ -3545,6 +3552,11 @@ DEF_METHOD(NV097, SET_SHADOW_ZSLOPE_THRESHOLD)
|
|||
assert(parameter == 0x7F800000); /* FIXME: Unimplemented */
|
||||
}
|
||||
|
||||
DEF_METHOD(NV097, SET_SHADOW_DEPTH_FUNC)
|
||||
{
|
||||
pg->shadow_depth_func = parameter;
|
||||
}
|
||||
|
||||
DEF_METHOD(NV097, SET_SHADER_STAGE_PROGRAM)
|
||||
{
|
||||
pg->regs[NV_PGRAPH_SHADERPROG] = parameter;
|
||||
|
@ -3845,6 +3857,7 @@ void pgraph_init(NV2AState *d)
|
|||
|
||||
pg->shader_cache = g_hash_table_new(shader_hash, shader_equal);
|
||||
|
||||
pg->shadow_depth_func = SHADOW_DEPTH_FUNC_NEVER;
|
||||
pg->material_alpha = 0.0f;
|
||||
|
||||
for (i=0; i<NV2A_VERTEXSHADER_ATTRIBUTES; i++) {
|
||||
|
@ -4242,6 +4255,8 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
|
|||
state.psh.point_sprite = pg->regs[NV_PGRAPH_SETUPRASTER] &
|
||||
NV_PGRAPH_SETUPRASTER_POINTSMOOTHENABLE;
|
||||
|
||||
state.psh.shadow_depth_func = pg->shadow_depth_func;
|
||||
|
||||
state.fixed_function = fixed_function;
|
||||
|
||||
/* fixed function stuff */
|
||||
|
@ -4385,6 +4400,8 @@ static void pgraph_bind_shaders(PGRAPHState *pg)
|
|||
state.psh.snorm_tex[i] = (f.gl_internal_format == GL_RGB8_SNORM)
|
||||
|| (f.gl_internal_format == GL_RG8_SNORM);
|
||||
|
||||
state.psh.shadow_map[i] = f.depth;
|
||||
|
||||
uint32_t filter = pg->regs[NV_PGRAPH_TEXFILTER0 + i*4];
|
||||
unsigned int min_filter = GET_MASK(filter, NV_PGRAPH_TEXFILTER0_MIN);
|
||||
enum ConvolutionFilter kernel = CONVOLUTION_FILTER_DISABLED;
|
||||
|
|
|
@ -177,6 +177,7 @@ DEF_METHOD(NV097, SET_SHADER_CLIP_PLANE_MODE)
|
|||
DEF_METHOD_RANGE(NV097, SET_COMBINER_COLOR_OCW, 8)
|
||||
DEF_METHOD(NV097, SET_COMBINER_CONTROL)
|
||||
DEF_METHOD(NV097, SET_SHADOW_ZSLOPE_THRESHOLD)
|
||||
DEF_METHOD(NV097, SET_SHADOW_DEPTH_FUNC)
|
||||
DEF_METHOD(NV097, SET_SHADER_STAGE_PROGRAM)
|
||||
DEF_METHOD(NV097, SET_DOT_RGBMAPPING)
|
||||
DEF_METHOD(NV097, SET_SHADER_OTHER_STAGE_INPUT)
|
||||
|
|
|
@ -558,6 +558,64 @@ static void add_final_stage_code(struct PixelShader *ps, struct FCInputInfo fina
|
|||
ps->varE = ps->varF = NULL;
|
||||
}
|
||||
|
||||
static const char sampler2D[] = "sampler2D";
|
||||
static const char sampler3D[] = "sampler3D";
|
||||
static const char samplerCube[] = "samplerCube";
|
||||
static const char sampler2DRect[] = "sampler2DRect";
|
||||
|
||||
static const char* get_sampler_type(enum PS_TEXTUREMODES mode, const PshState *state, int i)
|
||||
{
|
||||
switch (mode) {
|
||||
default:
|
||||
case PS_TEXTUREMODES_NONE:
|
||||
return NULL;
|
||||
|
||||
case PS_TEXTUREMODES_PROJECT2D:
|
||||
case PS_TEXTUREMODES_BUMPENVMAP:
|
||||
case PS_TEXTUREMODES_BUMPENVMAP_LUM:
|
||||
case PS_TEXTUREMODES_DOT_ST:
|
||||
if (state->shadow_map[i]) {
|
||||
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
|
||||
assert(!"Shadow map support not implemented for this mode");
|
||||
}
|
||||
return state->rect_tex[i] ? sampler2DRect : sampler2D;
|
||||
|
||||
case PS_TEXTUREMODES_PROJECT3D:
|
||||
case PS_TEXTUREMODES_DOT_STR_3D:
|
||||
if (state->shadow_map[i]) {
|
||||
return state->rect_tex[i] ? sampler2DRect : sampler2D;
|
||||
}
|
||||
return sampler3D;
|
||||
|
||||
case PS_TEXTUREMODES_CUBEMAP:
|
||||
case PS_TEXTUREMODES_DOT_RFLCT_DIFF:
|
||||
case PS_TEXTUREMODES_DOT_RFLCT_SPEC:
|
||||
case PS_TEXTUREMODES_DOT_STR_CUBE:
|
||||
if (state->shadow_map[i]) {
|
||||
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
|
||||
assert(!"Shadow map support not implemented for this mode");
|
||||
}
|
||||
return samplerCube;
|
||||
|
||||
case PS_TEXTUREMODES_DPNDNT_AR:
|
||||
case PS_TEXTUREMODES_DPNDNT_GB:
|
||||
if (state->shadow_map[i]) {
|
||||
fprintf(stderr, "Shadow map support not implemented for mode %d\n", mode);
|
||||
assert(!"Shadow map support not implemented for this mode");
|
||||
}
|
||||
return sampler2D;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *shadow_comparison_map[] = {
|
||||
[SHADOW_DEPTH_FUNC_LESS] = "<",
|
||||
[SHADOW_DEPTH_FUNC_EQUAL] = "==",
|
||||
[SHADOW_DEPTH_FUNC_LEQUAL] = "<=",
|
||||
[SHADOW_DEPTH_FUNC_GREATER] = ">",
|
||||
[SHADOW_DEPTH_FUNC_NOTEQUAL] = "!=",
|
||||
[SHADOW_DEPTH_FUNC_GEQUAL] = ">=",
|
||||
};
|
||||
|
||||
static MString* psh_convert(struct PixelShader *ps)
|
||||
{
|
||||
int i;
|
||||
|
@ -699,7 +757,7 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
||||
const char *sampler_type = NULL;
|
||||
const char *sampler_type = get_sampler_type(ps->tex_modes[i], &ps->state, i);
|
||||
|
||||
assert(ps->dot_map[i] < 8);
|
||||
const char *dotmap_func = dotmap_funcs[ps->dot_map[i]];
|
||||
|
@ -713,7 +771,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
i);
|
||||
break;
|
||||
case PS_TEXTUREMODES_PROJECT2D: {
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
const char *lookup = "textureProj";
|
||||
if ((ps->state.conv_tex[i] == CONVOLUTION_FILTER_GAUSSIAN)
|
||||
|| (ps->state.conv_tex[i] == CONVOLUTION_FILTER_QUINCUNX)) {
|
||||
|
@ -733,12 +790,38 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
break;
|
||||
}
|
||||
case PS_TEXTUREMODES_PROJECT3D:
|
||||
sampler_type = "sampler3D";
|
||||
mstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
|
||||
i, i, i);
|
||||
if (ps->state.shadow_map[i]) {
|
||||
if (ps->state.shadow_depth_func == SHADOW_DEPTH_FUNC_NEVER) {
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
|
||||
} else if (ps->state.shadow_depth_func == SHADOW_DEPTH_FUNC_ALWAYS) {
|
||||
mstring_append_fmt(vars, "vec4 t%d = vec4(1.0);\n", i);
|
||||
} else {
|
||||
mstring_append_fmt(vars,
|
||||
"pT%d.xy *= texScale%d;\n"
|
||||
"vec4 t%d_depth = textureProj(texSamp%d, pT%d.xyw);\n"
|
||||
"float t%d_max_depth;\n"
|
||||
"if (t%d_depth.y > 0) {\n"
|
||||
" t%d_max_depth = 0xFFFFFF;\n"
|
||||
"} else {\n"
|
||||
" t%d_max_depth = 0xFFFF; // TODO: Support float max.\n"
|
||||
"}\n"
|
||||
"t%d_depth.x *= t%d_max_depth;\n"
|
||||
"pT%d.z = clamp(pT%d.z / pT%d.w, 0, t%d_max_depth);\n",
|
||||
i, i, i, i, i,
|
||||
i, i, i, i, i,
|
||||
i, i, i, i, i);
|
||||
|
||||
const char *comparison = shadow_comparison_map[ps->state.shadow_depth_func];
|
||||
mstring_append_fmt(vars,
|
||||
"vec4 t%d = vec4(t%d_depth.x %s pT%d.z ? 1.0 : 0.0);\n",
|
||||
i, i, comparison, i);
|
||||
}
|
||||
} else {
|
||||
mstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
|
||||
i, i, i);
|
||||
}
|
||||
break;
|
||||
case PS_TEXTUREMODES_CUBEMAP:
|
||||
sampler_type = "samplerCube";
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xyz / pT%d.w);\n",
|
||||
i, i, i, i);
|
||||
break;
|
||||
|
@ -758,7 +841,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
}
|
||||
case PS_TEXTUREMODES_BUMPENVMAP:
|
||||
assert(i >= 1);
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
|
||||
|
||||
if (ps->state.snorm_tex[ps->input_tex[i]]) {
|
||||
|
@ -778,7 +860,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
break;
|
||||
case PS_TEXTUREMODES_BUMPENVMAP_LUM:
|
||||
assert(i >= 1);
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
mstring_append_fmt(preflight, "uniform float bumpScale%d;\n", i);
|
||||
mstring_append_fmt(preflight, "uniform float bumpOffset%d;\n", i);
|
||||
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
|
||||
|
@ -808,7 +889,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
break;
|
||||
case PS_TEXTUREMODES_DOT_ST:
|
||||
assert(i >= 2);
|
||||
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ST */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
|
@ -825,7 +905,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
break;
|
||||
case PS_TEXTUREMODES_DOT_RFLCT_DIFF:
|
||||
assert(i == 2);
|
||||
sampler_type = "samplerCube";
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_DIFF */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
|
@ -839,7 +918,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
break;
|
||||
case PS_TEXTUREMODES_DOT_RFLCT_SPEC:
|
||||
assert(i == 3);
|
||||
sampler_type = "samplerCube";
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_SPEC */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
|
@ -854,7 +932,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
break;
|
||||
case PS_TEXTUREMODES_DOT_STR_3D:
|
||||
assert(i == 3);
|
||||
sampler_type = "sampler3D";
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_3D */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
|
@ -863,7 +940,6 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
break;
|
||||
case PS_TEXTUREMODES_DOT_STR_CUBE:
|
||||
assert(i == 3);
|
||||
sampler_type = "samplerCube";
|
||||
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_CUBE */\n");
|
||||
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
|
||||
i, i, dotmap_func, ps->input_tex[i]);
|
||||
|
@ -873,14 +949,12 @@ static MString* psh_convert(struct PixelShader *ps)
|
|||
case PS_TEXTUREMODES_DPNDNT_AR:
|
||||
assert(i >= 1);
|
||||
assert(!ps->state.rect_tex[i]);
|
||||
sampler_type = "sampler2D";
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.ar);\n",
|
||||
i, i, ps->input_tex[i]);
|
||||
break;
|
||||
case PS_TEXTUREMODES_DPNDNT_GB:
|
||||
assert(i >= 1);
|
||||
assert(!ps->state.rect_tex[i]);
|
||||
sampler_type = "sampler2D";
|
||||
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.gb);\n",
|
||||
i, i, ps->input_tex[i]);
|
||||
break;
|
||||
|
@ -1063,7 +1137,5 @@ MString *psh_translate(const PshState state)
|
|||
ps.final_input.inv_r0 = flags & PS_FINALCOMBINERSETTING_COMPLEMENT_R0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return psh_convert(&ps);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,17 @@ enum PshAlphaFunc {
|
|||
ALPHA_FUNC_ALWAYS,
|
||||
};
|
||||
|
||||
enum PshShadowDepthFunc {
|
||||
SHADOW_DEPTH_FUNC_NEVER,
|
||||
SHADOW_DEPTH_FUNC_LESS,
|
||||
SHADOW_DEPTH_FUNC_EQUAL,
|
||||
SHADOW_DEPTH_FUNC_LEQUAL,
|
||||
SHADOW_DEPTH_FUNC_GREATER,
|
||||
SHADOW_DEPTH_FUNC_NOTEQUAL,
|
||||
SHADOW_DEPTH_FUNC_GEQUAL,
|
||||
SHADOW_DEPTH_FUNC_ALWAYS,
|
||||
};
|
||||
|
||||
enum ConvolutionFilter {
|
||||
CONVOLUTION_FILTER_DISABLED,
|
||||
CONVOLUTION_FILTER_QUINCUNX,
|
||||
|
@ -57,6 +68,9 @@ typedef struct PshState {
|
|||
bool alphakill[4];
|
||||
enum ConvolutionFilter conv_tex[4];
|
||||
|
||||
bool shadow_map[4];
|
||||
enum PshShadowDepthFunc shadow_depth_func;
|
||||
|
||||
bool alpha_test;
|
||||
enum PshAlphaFunc alpha_func;
|
||||
|
||||
|
|
Loading…
Reference in New Issue