diff --git a/hw/xbox/nv2a/nv2a_int.h b/hw/xbox/nv2a/nv2a_int.h index 69dd2ca720..f8dcacecf3 100644 --- a/hw/xbox/nv2a/nv2a_int.h +++ b/hw/xbox/nv2a/nv2a_int.h @@ -345,6 +345,8 @@ typedef struct PGRAPHState { uint32_t ltc1[NV2A_LTC1_COUNT][4]; bool ltc1_dirty[NV2A_LTC1_COUNT]; + float material_alpha; + // should figure out where these are in lighting context float light_infinite_half_vector[NV2A_MAX_LIGHTS][3]; float light_infinite_direction[NV2A_MAX_LIGHTS][3]; diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index de86c27029..4a9f18b0c4 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -982,6 +982,7 @@ # define NV097_SET_FRONT_FACE_V_CCW 0x901 # define NV097_SET_NORMALIZATION_ENABLE 0x000003A4 # define NV097_SET_MATERIAL_EMISSION 0x000003A8 +# define NV097_SET_MATERIAL_ALPHA 0x000003B4 # define NV097_SET_LIGHT_ENABLE_MASK 0x000003BC # define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_OFF 0 # define NV097_SET_LIGHT_ENABLE_MASK_LIGHT0_INFINITE 1 diff --git a/hw/xbox/nv2a/pgraph.c b/hw/xbox/nv2a/pgraph.c index b08f3afaa8..a1703be5c3 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -1894,6 +1894,11 @@ DEF_METHOD_INC(NV097, SET_MATERIAL_EMISSION) pg->ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_CM_COL] = true; } +DEF_METHOD(NV097, SET_MATERIAL_ALPHA) +{ + pg->material_alpha = *(float*)¶meter; +} + DEF_METHOD(NV097, SET_LIGHT_ENABLE_MASK) { SET_MASK(d->pgraph.regs[NV_PGRAPH_CSV0_D], @@ -3658,6 +3663,8 @@ void pgraph_init(NV2AState *d) pg->shader_cache = g_hash_table_new(shader_hash, shader_equal); + pg->material_alpha = 0.0f; + for (i=0; ivertex_attributes[i]; glGenBuffers(1, &attribute->gl_inline_buffer); @@ -3923,6 +3930,10 @@ static void pgraph_shader_update_constants(PGRAPHState *pg, glUniform4i(pg->shader_binding->clip_region_loc[i], x_min, y_min_xlat, x_max, y_max_xlat); } + + if (binding->material_alpha_loc != -1) { + glUniform1f(binding->material_alpha_loc, pg->material_alpha); + } } static bool pgraph_bind_shaders_test_dirty(PGRAPHState *pg) @@ -4052,18 +4063,19 @@ static void pgraph_bind_shaders(PGRAPHState *pg) /* fixed function stuff */ if (fixed_function) { - state.skinning = (enum VshSkinning)GET_MASK(pg->regs[NV_PGRAPH_CSV0_D], - NV_PGRAPH_CSV0_D_SKIN); - state.lighting = GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], - NV_PGRAPH_CSV0_C_LIGHTING); - state.normalization = pg->regs[NV_PGRAPH_CSV0_C] - & NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE; + state.skinning = (enum VshSkinning)GET_MASK(pg->regs[NV_PGRAPH_CSV0_D], + NV_PGRAPH_CSV0_D_SKIN); + state.lighting = GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], + NV_PGRAPH_CSV0_C_LIGHTING); + state.normalization = pg->regs[NV_PGRAPH_CSV0_C] + & NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE; - /* color material */ - state.emission_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_EMISSION); - state.ambient_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_AMBIENT); - state.diffuse_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_DIFFUSE); - state.specular_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_SPECULAR); + /* color material */ + state.emission_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_EMISSION); + state.ambient_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_AMBIENT); + state.diffuse_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_DIFFUSE); + state.specular_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_SPECULAR); + state.material_alpha = pg->material_alpha; } /* vertex program stuff */ diff --git a/hw/xbox/nv2a/pgraph_methods.h b/hw/xbox/nv2a/pgraph_methods.h index 8bd6e62657..fb29b51e26 100644 --- a/hw/xbox/nv2a/pgraph_methods.h +++ b/hw/xbox/nv2a/pgraph_methods.h @@ -76,6 +76,7 @@ DEF_METHOD(NV097, SET_CULL_FACE) DEF_METHOD(NV097, SET_FRONT_FACE) DEF_METHOD(NV097, SET_NORMALIZATION_ENABLE) DEF_METHOD_RANGE(NV097, SET_MATERIAL_EMISSION, 3) +DEF_METHOD(NV097, SET_MATERIAL_ALPHA) DEF_METHOD(NV097, SET_LIGHT_ENABLE_MASK) DEF_METHOD_CASE_4(NV097, SET_TEXGEN_S, 16) DEF_METHOD_CASE_4(NV097, SET_TEXGEN_T, 16) diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index 91519068d8..da70006707 100644 --- a/hw/xbox/nv2a/shaders.c +++ b/hw/xbox/nv2a/shaders.c @@ -488,12 +488,23 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz //FIXME: Do 2 passes if we want 2 sided-lighting? + static char alpha_source_diffuse[] = "diffuse.a"; + static char alpha_source_specular[] = "specular.a"; + static char alpha_source_material[] = "material_alpha"; + const char *alpha_source = alpha_source_diffuse; + if (state.diffuse_src == MATERIAL_COLOR_SRC_MATERIAL) { + mstring_append(header, "uniform float material_alpha;\n"); + alpha_source = alpha_source_material; + } else if (state.diffuse_src == MATERIAL_COLOR_SRC_SPECULAR) { + alpha_source = alpha_source_specular; + } + if (state.ambient_src == MATERIAL_COLOR_SRC_MATERIAL) { - mstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n"); + mstring_append_fmt(body, "oD0 = vec4(sceneAmbientColor, %s);\n", alpha_source); } else if (state.ambient_src == MATERIAL_COLOR_SRC_DIFFUSE) { - mstring_append(body, "oD0 = vec4(diffuse.rgb, diffuse.a);\n"); + mstring_append_fmt(body, "oD0 = vec4(diffuse.rgb, %s);\n", alpha_source); } else if (state.ambient_src == MATERIAL_COLOR_SRC_SPECULAR) { - mstring_append(body, "oD0 = vec4(specular.rgb, diffuse.a);\n"); + mstring_append_fmt(body, "oD0 = vec4(specular.rgb, %s);\n", alpha_source); } mstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n"); @@ -602,8 +613,20 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz mstring_append(body, " oD0.xyz += lightAmbient;\n"); - mstring_append(body, - " oD0.xyz += diffuse.xyz * lightDiffuse;\n"); + switch (state.diffuse_src) { + case MATERIAL_COLOR_SRC_MATERIAL: + mstring_append(body, + " oD0.xyz += lightDiffuse;\n"); + break; + case MATERIAL_COLOR_SRC_DIFFUSE: + mstring_append(body, + " oD0.xyz += diffuse.xyz * lightDiffuse;\n"); + break; + case MATERIAL_COLOR_SRC_SPECULAR: + mstring_append(body, + " oD0.xyz += specular.xyz * lightDiffuse;\n"); + break; + } mstring_append(body, " oD1.xyz += specular.xyz * lightSpecular;\n"); @@ -1059,5 +1082,11 @@ ShaderBinding* generate_shaders(const ShaderState state) ret->clip_region_loc[i] = glGetUniformLocation(program, tmp); } + if (state.fixed_function) { + ret->material_alpha_loc = glGetUniformLocation(program, "material_alpha"); + } else { + ret->material_alpha_loc = -1; + } + return ret; } diff --git a/hw/xbox/nv2a/shaders.h b/hw/xbox/nv2a/shaders.h index abcd2b737f..2acebcded5 100644 --- a/hw/xbox/nv2a/shaders.h +++ b/hw/xbox/nv2a/shaders.h @@ -76,6 +76,8 @@ typedef struct ShaderState { enum MaterialColorSource diffuse_src; enum MaterialColorSource specular_src; + float material_alpha; + bool lighting; enum VshLight light[NV2A_MAX_LIGHTS]; @@ -128,6 +130,8 @@ typedef struct ShaderBinding { GLint light_local_attenuation_loc[NV2A_MAX_LIGHTS]; GLint clip_region_loc[8]; + + GLint material_alpha_loc; } ShaderBinding; ShaderBinding* generate_shaders(const ShaderState state);