From 517e4b34148f77cb8b7bfbaccaf0e6f22d21082f Mon Sep 17 00:00:00 2001 From: Erik Abair Date: Fri, 17 Dec 2021 23:08:49 -0800 Subject: [PATCH] nv2a: Implement SET_MATERIAL_ALPHA and diffuse color src This adds support for the material alpha command and updates the fixed function shader to respect the diffuse source parameter (which was already piped through but not utilized). --- hw/xbox/nv2a/nv2a_int.h | 2 ++ hw/xbox/nv2a/nv2a_regs.h | 1 + hw/xbox/nv2a/pgraph.c | 34 ++++++++++++++++++++---------- hw/xbox/nv2a/pgraph_methods.h | 1 + hw/xbox/nv2a/shaders.c | 39 ++++++++++++++++++++++++++++++----- hw/xbox/nv2a/shaders.h | 4 ++++ 6 files changed, 65 insertions(+), 16 deletions(-) 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);