diff --git a/hw/xbox/nv2a/nv2a_pgraph.c b/hw/xbox/nv2a/nv2a_pgraph.c index 185bafacd9..537c7b28d4 100644 --- a/hw/xbox/nv2a/nv2a_pgraph.c +++ b/hw/xbox/nv2a/nv2a_pgraph.c @@ -898,7 +898,12 @@ static void pgraph_method(NV2AState *d, z_perspective); break; } - + case NV097_SET_COLOR_MATERIAL: + SET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_EMISSION, (parameter >> 0) & 3); + SET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_AMBIENT, (parameter >> 2) & 3); + SET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_DIFFUSE, (parameter >> 4) & 3); + SET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_SPECULAR, (parameter >> 6) & 3); + break; case NV097_SET_FOG_MODE: { /* FIXME: There is also NV_PGRAPH_CSV0_D_FOG_MODE */ unsigned int mode; @@ -1269,6 +1274,14 @@ static void pgraph_method(NV2AState *d, parameter); break; + case NV097_SET_MATERIAL_EMISSION ... + NV097_SET_MATERIAL_EMISSION + 8: + slot = (method - NV097_SET_MATERIAL_EMISSION) / 4; + // FIXME: Verify NV_IGRAPH_XF_LTCTXA_CM_COL is correct + pg->ltctxa[NV_IGRAPH_XF_LTCTXA_CM_COL][slot] = parameter; + pg->ltctxa_dirty[NV_IGRAPH_XF_LTCTXA_CM_COL] = true; + break; + case NV097_SET_LIGHT_ENABLE_MASK: SET_MASK(d->pgraph.regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_LIGHTS, @@ -3059,6 +3072,12 @@ static void pgraph_bind_shaders(PGRAPHState *pg) .normalization = pg->regs[NV_PGRAPH_CSV0_C] & NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE, + /* color material */ + .emission_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_EMISSION), + .ambient_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_AMBIENT), + .diffuse_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_DIFFUSE), + .specular_src = (enum MaterialColorSource)GET_MASK(pg->regs[NV_PGRAPH_CSV0_C], NV_PGRAPH_CSV0_C_SPECULAR), + .fixed_function = fixed_function, /* vertex program stuff */ diff --git a/hw/xbox/nv2a/nv2a_regs.h b/hw/xbox/nv2a/nv2a_regs.h index 7743f5ba05..735c8c8f95 100644 --- a/hw/xbox/nv2a/nv2a_regs.h +++ b/hw/xbox/nv2a/nv2a_regs.h @@ -300,6 +300,10 @@ # define NV_PGRAPH_CSV0_D_SKIN_4 6 #define NV_PGRAPH_CSV0_C 0x00000FB8 # define NV_PGRAPH_CSV0_C_CHEOPS_PROGRAM_START 0x0000FF00 +# define NV_PGRAPH_CSV0_C_SPECULAR (3 << 19) +# define NV_PGRAPH_CSV0_C_DIFFUSE (3 << 21) +# define NV_PGRAPH_CSV0_C_AMBIENT (3 << 23) +# define NV_PGRAPH_CSV0_C_EMISSION (3 << 25) # define NV_PGRAPH_CSV0_C_NORMALIZATION_ENABLE (1 << 27) # define NV_PGRAPH_CSV0_C_LIGHTING (1 << 31) #define NV_PGRAPH_CSV1_B 0x00000FBC @@ -816,6 +820,7 @@ # define NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE (1 << 0) # define NV097_SET_CONTROL0_Z_FORMAT (1 << 12) # define NV097_SET_CONTROL0_Z_PERSPECTIVE_ENABLE (1 << 16) +# define NV097_SET_COLOR_MATERIAL 0x00000298 # define NV097_SET_FOG_MODE 0x0000029C # define NV097_SET_FOG_MODE_V_LINEAR 0x2601 # define NV097_SET_FOG_MODE_V_EXP 0x800 @@ -940,6 +945,7 @@ # define NV097_SET_FRONT_FACE_V_CW 0x900 # define NV097_SET_FRONT_FACE_V_CCW 0x901 # define NV097_SET_NORMALIZATION_ENABLE 0x000003A4 +# define NV097_SET_MATERIAL_EMISSION 0x000003A8 # 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/nv2a_shaders.c b/hw/xbox/nv2a/nv2a_shaders.c index eb4192e7ff..d02968aa5a 100644 --- a/hw/xbox/nv2a/nv2a_shaders.c +++ b/hw/xbox/nv2a/nv2a_shaders.c @@ -3,6 +3,7 @@ * * Copyright (c) 2015 espes * Copyright (c) 2015 Jannik Vogel + * Copyright (c) 2020 Matt Borgerson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -364,6 +365,7 @@ GLSL_DEFINE(eyePosition, GLSL_C(NV_IGRAPH_XF_XFCTX_EYEP)) "ltc1[" stringify(NV_IGRAPH_XF_LTC1_r0) " + (i)].x\n" "\n" GLSL_DEFINE(sceneAmbientColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_FR_AMB) ".xyz") +GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz") "\n" "uniform mat4 invViewport;\n" "\n"); @@ -484,7 +486,24 @@ GLSL_DEFINE(sceneAmbientColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_FR_AMB) ".xyz") if (state.lighting) { //FIXME: Do 2 passes if we want 2 sided-lighting? - qstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n"); + + if (state.ambient_src == MATERIAL_COLOR_SRC_MATERIAL) { + qstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n"); + } else if (state.ambient_src == MATERIAL_COLOR_SRC_DIFFUSE) { + qstring_append(body, "oD0 = vec4(diffuse.rgb, diffuse.a);\n"); + } else if (state.ambient_src == MATERIAL_COLOR_SRC_SPECULAR) { + qstring_append(body, "oD0 = vec4(specular.rgb, diffuse.a);\n"); + } + + qstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n"); + if (state.emission_src == MATERIAL_COLOR_SRC_MATERIAL) { + qstring_append(body, "oD0.rgb += sceneAmbientColor;\n"); + } else if (state.emission_src == MATERIAL_COLOR_SRC_DIFFUSE) { + qstring_append(body, "oD0.rgb += diffuse.rgb;\n"); + } else if (state.emission_src == MATERIAL_COLOR_SRC_SPECULAR) { + qstring_append(body, "oD0.rgb += specular.rgb;\n"); + } + qstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n"); for (i = 0; i < NV2A_MAX_LIGHTS; i++) { diff --git a/hw/xbox/nv2a/nv2a_shaders.h b/hw/xbox/nv2a/nv2a_shaders.h index 3b724dad3f..64366a38de 100644 --- a/hw/xbox/nv2a/nv2a_shaders.h +++ b/hw/xbox/nv2a/nv2a_shaders.h @@ -48,6 +48,12 @@ enum ShaderPolygonMode { POLY_MODE_LINE, }; +enum MaterialColorSource { + MATERIAL_COLOR_SRC_MATERIAL, + MATERIAL_COLOR_SRC_DIFFUSE, + MATERIAL_COLOR_SRC_SPECULAR, +}; + typedef struct ShaderState { PshState psh; @@ -62,6 +68,11 @@ typedef struct ShaderState { bool normalization; + enum MaterialColorSource emission_src; + enum MaterialColorSource ambient_src; + enum MaterialColorSource diffuse_src; + enum MaterialColorSource specular_src; + bool lighting; enum VshLight light[NV2A_MAX_LIGHTS];