From 78a3163925469e47a7e9aff1732cbbbbd0aca222 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 25 Jul 2015 13:05:15 +0200 Subject: [PATCH 1/6] Add fog states --- hw/xbox/nv2a.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 5f95d45608..68c83d3fcd 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -261,9 +261,19 @@ # define NV_PGRAPH_CHANNEL_CTX_TRIGGER_WRITE_OUT (1 << 1) #define NV_PGRAPH_CSV0_D 0x00000FB4 # define NV_PGRAPH_CSV0_D_RANGE_MODE (1 << 18) +# define NV_PGRAPH_CSV0_D_FOGENABLE (1 << 19) # define NV_PGRAPH_CSV0_D_TEXGEN_REF (1 << 20) # define NV_PGRAPH_CSV0_D_TEXGEN_REF_LOCAL_VIEWER 0 # define NV_PGRAPH_CSV0_D_TEXGEN_REF_INFINITE_VIEWER 1 +# define NV_PGRAPH_CSV0_D_FOG_MODE (1 << 21) +# define NV_PGRAPH_CSV0_D_FOG_MODE_LINEAR 0 +# define NV_PGRAPH_CSV0_D_FOG_MODE_EXP 1 +# define NV_PGRAPH_CSV0_D_FOGGENMODE 0x01C00000 +# define NV_PGRAPH_CSV0_D_FOGGENMODE_SPEC_ALPHA 0 +# define NV_PGRAPH_CSV0_D_FOGGENMODE_RADIAL 1 +# define NV_PGRAPH_CSV0_D_FOGGENMODE_PLANAR 2 +# define NV_PGRAPH_CSV0_D_FOGGENMODE_ABS_PLANAR 3 +# define NV_PGRAPH_CSV0_D_FOGGENMODE_FOG_X 4 # define NV_PGRAPH_CSV0_D_MODE 0xC0000000 # define NV_PGRAPH_CSV0_D_SKIN 0x1C000000 # define NV_PGRAPH_CSV0_D_SKIN_OFF 0 @@ -405,6 +415,22 @@ # define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INVERT 6 # define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_INCR 7 # define NV_PGRAPH_CONTROL_2_STENCIL_OP_V_DECR 8 +#define NV_PGRAPH_CONTROL_3 0x00001958 +# define NV_PGRAPH_CONTROL_3_FOGENABLE (1 << 8) +# define NV_PGRAPH_CONTROL_3_FOG_MODE 0x00070000 +# define NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR 0 +# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP 1 +# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2 3 +# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP_ABS 5 +# define NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2_ABS 7 +# define NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR_ABS 4 +#define NV_PGRAPH_FOGCOLOR 0x00001980 +# define NV_PGRAPH_FOGCOLOR_RED 0x00FF0000 +# define NV_PGRAPH_FOGCOLOR_GREEN 0x0000FF00 +# define NV_PGRAPH_FOGCOLOR_BLUE 0x000000FF +# define NV_PGRAPH_FOGCOLOR_ALPHA 0xFF000000 +#define NV_PGRAPH_FOGPARAM0 0x00001984 +#define NV_PGRAPH_FOGPARAM1 0x00001988 #define NV_PGRAPH_SETUPRASTER 0x00001990 # define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE 0x00000003 # define NV_PGRAPH_SETUPRASTER_FRONTFACEMODE_FILL 0 @@ -716,6 +742,25 @@ # define NV097_SET_CONTROL0 0x00970290 # define NV097_SET_CONTROL0_STENCIL_WRITE_ENABLE (1 << 0) # define NV097_SET_CONTROL0_Z_FORMAT (1 << 12) +# define NV097_SET_FOG_MODE 0x0097029C +# define NV097_SET_FOG_MODE_V_LINEAR 0x2601 +# define NV097_SET_FOG_MODE_V_EXP 0x800 +# define NV097_SET_FOG_MODE_V_EXP2 0x801 +# define NV097_SET_FOG_MODE_V_EXP_ABS 0x802 +# define NV097_SET_FOG_MODE_V_EXP2_ABS 0x803 +# define NV097_SET_FOG_MODE_V_LINEAR_ABS 0x804 +# define NV097_SET_FOG_GEN_MODE 0x009702A0 +# define NV097_SET_FOG_GEN_MODE_V_SPEC_ALPHA 0 +# define NV097_SET_FOG_GEN_MODE_V_RADIAL 1 +# define NV097_SET_FOG_GEN_MODE_V_PLANAR 2 +# define NV097_SET_FOG_GEN_MODE_V_ABS_PLANAR 3 +# define NV097_SET_FOG_GEN_MODE_V_FOG_X 6 +# define NV097_SET_FOG_ENABLE 0x009702A4 +# define NV097_SET_FOG_COLOR 0x009702A8 +# define NV097_SET_FOG_COLOR_RED 0x000000FF +# define NV097_SET_FOG_COLOR_GREEN 0x0000FF00 +# define NV097_SET_FOG_COLOR_BLUE 0x00FF0000 +# define NV097_SET_FOG_COLOR_ALPHA 0xFF000000 # define NV097_SET_ALPHA_TEST_ENABLE 0x00970300 # define NV097_SET_BLEND_ENABLE 0x00970304 # define NV097_SET_CULL_FACE_ENABLE 0x00970308 @@ -825,9 +870,11 @@ # define NV097_SET_INVERSE_MODEL_VIEW_MATRIX 0x00970580 # define NV097_SET_COMPOSITE_MATRIX 0x00970680 # define NV097_SET_TEXTURE_MATRIX 0x009706C0 +# define NV097_SET_FOG_PARAMS 0x009709C0 # define NV097_SET_TEXGEN_VIEW_MODEL 0x009709CC # define NV097_SET_TEXGEN_VIEW_MODEL_LOCAL_VIEWER 0 # define NV097_SET_TEXGEN_VIEW_MODEL_INFINITE_VIEWER 1 +# define NV097_SET_FOG_PLANE 0x009709D0 # define NV097_SET_VIEWPORT_OFFSET 0x00970A20 # define NV097_SET_COMBINER_FACTOR0 0x00970A60 # define NV097_SET_COMBINER_FACTOR1 0x00970A80 @@ -1452,6 +1499,9 @@ typedef struct PGRAPHState { float inverse_model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */ float model_view_matrix[4][16]; /* 4 weights with 4x4 matrix each */ + /* FIXME: Also in vshader consts? */ + float fog_plane[4]; + /* FIXME: Move to NV_PGRAPH_BUMPMAT... */ float bump_env_matrix[3][4]; /* 4 stages with 2x2 matrix each */ @@ -3907,6 +3957,71 @@ static void pgraph_method(NV2AState *d, break; } + case NV097_SET_FOG_MODE: { + /* FIXME: There is also NV_PGRAPH_CSV0_D_FOG_MODE */ + unsigned int mode; + switch (parameter) { + case NV097_SET_FOG_MODE_V_LINEAR: + mode = NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR; break; + case NV097_SET_FOG_MODE_V_EXP: + mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP; break; + case NV097_SET_FOG_MODE_V_EXP2: + mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2; break; + case NV097_SET_FOG_MODE_V_EXP_ABS: + mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP_ABS; break; + case NV097_SET_FOG_MODE_V_EXP2_ABS: + mode = NV_PGRAPH_CONTROL_3_FOG_MODE_EXP2_ABS; break; + case NV097_SET_FOG_MODE_V_LINEAR_ABS: + mode = NV_PGRAPH_CONTROL_3_FOG_MODE_LINEAR_ABS; break; + default: + assert(false); + break; + } + SET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_FOG_MODE, + mode); + break; + } + case NV097_SET_FOG_GEN_MODE: { + unsigned int mode; + switch (parameter) { + case NV097_SET_FOG_GEN_MODE_V_SPEC_ALPHA: + mode = NV_PGRAPH_CSV0_D_FOGGENMODE_SPEC_ALPHA; break; + case NV097_SET_FOG_GEN_MODE_V_RADIAL: + mode = NV_PGRAPH_CSV0_D_FOGGENMODE_RADIAL; break; + case NV097_SET_FOG_GEN_MODE_V_PLANAR: + mode = NV_PGRAPH_CSV0_D_FOGGENMODE_PLANAR; break; + case NV097_SET_FOG_GEN_MODE_V_ABS_PLANAR: + mode = NV_PGRAPH_CSV0_D_FOGGENMODE_ABS_PLANAR; break; + case NV097_SET_FOG_GEN_MODE_V_FOG_X: + mode = NV_PGRAPH_CSV0_D_FOGGENMODE_FOG_X; break; + default: + assert(false); + break; + } + SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_FOGGENMODE, mode); + break; + } + case NV097_SET_FOG_ENABLE: +/* + FIXME: There is also: + SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_FOGENABLE, + parameter); +*/ + SET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], NV_PGRAPH_CONTROL_3_FOGENABLE, + parameter); + break; + case NV097_SET_FOG_COLOR: { + /* PGRAPH channels are ARGB, parameter channels are ABGR */ + uint8_t red = GET_MASK(parameter, NV097_SET_FOG_COLOR_RED); + uint8_t green = GET_MASK(parameter, NV097_SET_FOG_COLOR_GREEN); + uint8_t blue = GET_MASK(parameter, NV097_SET_FOG_COLOR_BLUE); + uint8_t alpha = GET_MASK(parameter, NV097_SET_FOG_COLOR_ALPHA); + SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_RED, red); + SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_GREEN, green); + SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_BLUE, blue); + SET_MASK(pg->regs[NV_PGRAPH_FOGCOLOR], NV_PGRAPH_FOGCOLOR_ALPHA, alpha); + break; + } case NV097_SET_ALPHA_TEST_ENABLE: SET_MASK(pg->regs[NV_PGRAPH_CONTROL_0], NV_PGRAPH_CONTROL_0_ALPHATESTENABLE, parameter); @@ -4240,11 +4355,22 @@ static void pgraph_method(NV2AState *d, pg->texture_matrix[slot / 16][slot % 16] = *(float*)¶meter; break; + case NV097_SET_FOG_PARAMS ... + NV097_SET_FOG_PARAMS + 8: + slot = (class_method - NV097_SET_FOG_PARAMS) / 4; + pg->regs[NV_PGRAPH_FOGPARAM0 + slot*4] = parameter; + break; case NV097_SET_TEXGEN_VIEW_MODEL: SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_TEXGEN_REF, parameter); break; + case NV097_SET_FOG_PLANE ... + NV097_SET_FOG_PLANE + 12: + slot = (class_method - NV097_SET_FOG_PLANE) / 4; + pg->fog_plane[slot] = *(float*)¶meter; + break; + case NV097_SET_VIEWPORT_OFFSET ... NV097_SET_VIEWPORT_OFFSET + 12: From 177a4d78f868d335c240e0d34bf6514b17f8fb36 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sat, 25 Jul 2015 21:01:17 +0200 Subject: [PATCH 2/6] Foggen + Fog WIP --- hw/xbox/nv2a.c | 56 +++++++++++++++++++++++++++- hw/xbox/nv2a_psh.c | 5 +-- hw/xbox/nv2a_shaders.c | 84 +++++++++++++++++++++++++++++++++++++++++- hw/xbox/nv2a_shaders.h | 4 ++ hw/xbox/nv2a_vsh.h | 21 +++++++++++ 5 files changed, 164 insertions(+), 6 deletions(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 68c83d3fcd..c2a59846d6 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -2838,6 +2838,21 @@ static void pgraph_bind_shaders(PGRAPHState *pg) } } + /* Fog */ + state.fog_enable = pg->regs[NV_PGRAPH_CONTROL_3] + & NV_PGRAPH_CONTROL_3_FOGENABLE; + if (state.fog_enable) { + /*FIXME: Use CSV0_D? */ + state.fog_mode = GET_MASK(pg->regs[NV_PGRAPH_CONTROL_3], + NV_PGRAPH_CONTROL_3_FOG_MODE); + state.foggen = GET_MASK(pg->regs[NV_PGRAPH_CSV0_D], + NV_PGRAPH_CSV0_D_FOGGENMODE); + } else { + /* FIXME: Do we still pass the fogmode? */ + state.fog_mode = 0; + state.foggen = 0; + } + /* Texture matrices */ for (i = 0; i < 4; i++) { state.texture_matrix_enable[i] = pg->texture_matrix_enable[i]; @@ -2962,6 +2977,39 @@ static void pgraph_bind_shaders(PGRAPHState *pg) } + /* Fog */ + { + GLint loc; + uint32_t fog_color = pg->regs[NV_PGRAPH_FOGCOLOR]; + loc = glGetUniformLocation(pg->shader_binding->gl_program, "fogColor"); + if (loc != -1) { + glUniform4f(loc, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_RED) / 255.0, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_GREEN) / 255.0, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_BLUE) / 255.0, + GET_MASK(fog_color, NV_PGRAPH_FOGCOLOR_ALPHA) / 255.0); + } + + /* FIXME: PGRAPH regs have a 16 byte stride in emulation! can't just + * upload this as an array =( + */ + loc = glGetUniformLocation(pg->shader_binding->gl_program, + "fogParam[0]"); + if (loc != -1) { + glUniform1f(loc, *(float*)&pg->regs[NV_PGRAPH_FOGPARAM0]); + } + loc = glGetUniformLocation(pg->shader_binding->gl_program, + "fogParam[1]"); + if (loc != -1) { + glUniform1f(loc, *(float*)&pg->regs[NV_PGRAPH_FOGPARAM1]); + } + + loc = glGetUniformLocation(pg->shader_binding->gl_program, "fogPlane"); + if (loc != -1) { + glUniform4fv(loc, 1, pg->fog_plane); + } + } + /* For each vertex weight */ for (i = 0; i < 4; i++) { char name[32]; @@ -4358,7 +4406,11 @@ static void pgraph_method(NV2AState *d, case NV097_SET_FOG_PARAMS ... NV097_SET_FOG_PARAMS + 8: slot = (class_method - NV097_SET_FOG_PARAMS) / 4; - pg->regs[NV_PGRAPH_FOGPARAM0 + slot*4] = parameter; + if (slot < 2) { + pg->regs[NV_PGRAPH_FOGPARAM0 + slot*4] = parameter; + } else { + /* FIXME: No idea where slot = 2 is */ + } break; case NV097_SET_TEXGEN_VIEW_MODEL: SET_MASK(pg->regs[NV_PGRAPH_CSV0_D], NV_PGRAPH_CSV0_D_TEXGEN_REF, @@ -6783,7 +6835,7 @@ static void pgraph_method_log(unsigned int subchannel, static unsigned int last = 0; static unsigned int count = 0; if (last == 0x1800 && method != last) { - NV2A_DPRINTF("pgraph method (%d) 0x%x * %d", + NV2A_GL_DPRINTF(true, "pgraph method (%d) 0x%x * %d", subchannel, last, count); } if (method != 0x1800) { diff --git a/hw/xbox/nv2a_psh.c b/hw/xbox/nv2a_psh.c index 47d2baeb6c..a34c1b6a95 100644 --- a/hw/xbox/nv2a_psh.c +++ b/hw/xbox/nv2a_psh.c @@ -280,9 +280,8 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) return qstring_from_str("c_0_1"); } break; - case PS_REGISTER_FOG: // TODO - //return qstring_from_str("fog"); - return qstring_from_str("vec4(1.0)"); + case PS_REGISTER_FOG: + return qstring_from_str("clamp(pFog, 0.0, 1.0)"); case PS_REGISTER_V0: return qstring_from_str("v0"); case PS_REGISTER_V1: diff --git a/hw/xbox/nv2a_shaders.c b/hw/xbox/nv2a_shaders.c index f94a286340..e18940f8cd 100644 --- a/hw/xbox/nv2a_shaders.c +++ b/hw/xbox/nv2a_shaders.c @@ -115,6 +115,9 @@ static QString* generate_fixed_function(const ShaderState state, qstring_append(s, "\n" /* FIXME: Add these uniforms using code when they are used */ +"uniform vec4 fogColor;\n" +"uniform vec4 fogPlane;\n" +"uniform float fogParam[2];\n" "uniform mat4 texMat0;\n" "uniform mat4 texMat1;\n" "uniform mat4 texMat2;\n" @@ -255,6 +258,85 @@ static QString* generate_fixed_function(const ShaderState state, } } + /* Fog */ + if (state.fog_enable) { + + /* From: https://www.opengl.org/registry/specs/NV/fog_distance.txt */ + switch(state.foggen) { + case FOGGEN_SPEC_ALPHA: + assert(false); /* FIXME: Do this before or after calculations in VSH? */ + if (state.fixed_function) { + /* FIXME: Do we have to clamp here? */ + qstring_append(s, "float fogDistance = clamp(specular.a, 0.0, 1.0);\n"); + } else if (state.vertex_program) { + qstring_append(s, "float fogDistance = oD1.a;\n"); + } else { + assert(false); + } + break; + case FOGGEN_RADIAL: + qstring_append(s, "float fogDistance = length(tPosition.xyz)"); + break; + case FOGGEN_PLANAR: + case FOGGEN_ABS_PLANAR: + qstring_append(s, "float fogDistance = dot(fogPlane.xyz,tPosition.xyz)+fogPlane.w;\n"); + if (state.foggen == FOGGEN_ABS_PLANAR) { + qstring_append(s, "fogDistance = abs(fogDistance);\n"); + } + break; + case FOGGEN_FOG_X: + if (state.fixed_function) { + qstring_append(s, "float fogDistance = fogCoord;\n"); + } else if (state.vertex_program) { + qstring_append(s, "float fogDistance = oFog.x;\n"); + } else { + assert(false); + } + break; + default: + assert(false); + break; + } + + switch (state.fog_mode) { + case FOG_MODE_LINEAR: + case FOG_MODE_LINEAR_ABS: + qstring_append(s, "float fogFactor = fogDistance * fogParam[1] + fogParam[0];\n"); + qstring_append(s, "fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */ + break; + case FOG_MODE_EXP: + case FOG_MODE_EXP_ABS: + assert(false); /* FIXME: fogParam[0] and fogParam[0] ?? */ + qstring_append(s, "float fogFactor = exp(fogDistance);\n"); + break; + case FOG_MODE_EXP2: + case FOG_MODE_EXP2_ABS: + assert(false); /* FIXME: fogParam[0] and fogParam[0] ?? */ + qstring_append(s, "float fogFactor = exp(fogDistance * fogDistance);\n"); + break; + default: + assert(false); + break; + } + /* Calculate absolute for the modes which need it */ + switch (state.fog_mode) { + case FOG_MODE_LINEAR_ABS: + case FOG_MODE_EXP_ABS: + case FOG_MODE_EXP2_ABS: + qstring_append(s, "fogFactor = abs(fogFactor);\n"); + break; + default: + break; + } + /* FIXME: What about fog alpha?! */ + qstring_append(s, "vec4 tFog = vec4(fogColor.rgb, fogFactor);\n"); + } else { + /* FIXME: Is the fog still calculated / passed somehow?! + * Maybe vec4(fogColor, fogCoord) ? + */ + qstring_append(s, "vec4 tFog = vec4(0.0);\n"); + } + /* If skinning is off the composite matrix already includes the MV matrix */ if (state.skinning == SKINNING_OFF) { qstring_append(s, "tPosition = position;\n"); @@ -273,7 +355,7 @@ static QString* generate_fixed_function(const ShaderState state, qstring_append(s, "vtx.D1 = specular * vtx.inv_w;\n"); qstring_append(s, "vtx.B0 = backDiffuse * vtx.inv_w;\n"); qstring_append(s, "vtx.B1 = backSpecular * vtx.inv_w;\n"); - qstring_append(s, "vtx.Fog = vec4(0.0,0.0,0.0,1.0) * vtx.inv_w;\n"); + qstring_append(s, "vtx.Fog = tFog * vtx.inv_w;\n"); qstring_append(s, "vtx.T0 = tTexture0 * vtx.inv_w;\n"); qstring_append(s, "vtx.T1 = tTexture1 * vtx.inv_w;\n"); qstring_append(s, "vtx.T2 = tTexture2 * vtx.inv_w;\n"); diff --git a/hw/xbox/nv2a_shaders.h b/hw/xbox/nv2a_shaders.h index 56f82b8707..3271cb5415 100644 --- a/hw/xbox/nv2a_shaders.h +++ b/hw/xbox/nv2a_shaders.h @@ -65,6 +65,10 @@ typedef struct ShaderState { bool texture_matrix_enable[4]; enum VshTexgen texgen[4][4]; + bool fog_enable; + enum VshFoggen foggen; + enum VshFogMode fog_mode; + enum VshSkinning skinning; bool normalization; diff --git a/hw/xbox/nv2a_vsh.h b/hw/xbox/nv2a_vsh.h index bb23b1dad9..8cb49e9ccf 100644 --- a/hw/xbox/nv2a_vsh.h +++ b/hw/xbox/nv2a_vsh.h @@ -33,6 +33,27 @@ enum VshTexgen { TEXGEN_REFLECTION_MAP, }; +enum VshFogMode { + FOG_MODE_LINEAR, + FOG_MODE_EXP, + FOG_MODE_ERROR2, /* Doesn't exist */ + FOG_MODE_EXP2, + FOG_MODE_LINEAR_ABS, + FOG_MODE_EXP_ABS, + FOG_MODE_ERROR6, /* Doesn't exist */ + FOG_MODE_EXP2_ABS +}; + +enum VshFoggen { + FOGGEN_SPEC_ALPHA, + FOGGEN_RADIAL, + FOGGEN_PLANAR, + FOGGEN_ABS_PLANAR, + FOGGEN_ERROR4, + FOGGEN_ERROR5, + FOGGEN_FOG_X +}; + enum VshSkinning { SKINNING_OFF, SKINNING_1WEIGHTS, From 573d2e87c720752b720c6ae31d6d8d978cfc1ad2 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Sun, 26 Jul 2015 00:41:32 +0200 Subject: [PATCH 3/6] Clamp pFog instead of clamping access --- hw/xbox/nv2a_psh.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/xbox/nv2a_psh.c b/hw/xbox/nv2a_psh.c index a34c1b6a95..ae69c53d2d 100644 --- a/hw/xbox/nv2a_psh.c +++ b/hw/xbox/nv2a_psh.c @@ -281,7 +281,7 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest) } break; case PS_REGISTER_FOG: - return qstring_from_str("clamp(pFog, 0.0, 1.0)"); + return qstring_from_str("pFog"); case PS_REGISTER_V0: return qstring_from_str("v0"); case PS_REGISTER_V1: @@ -546,7 +546,7 @@ static QString* psh_convert(struct PixelShader *ps) qstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n"); - qstring_append(vars, "vec4 pFog = vtx.Fog / vtx.inv_w;\n"); + qstring_append(vars, "vec4 pFog = clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0);\n"); qstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n"); @@ -554,7 +554,6 @@ static QString* psh_convert(struct PixelShader *ps) qstring_append(vars, "\n"); qstring_append(vars, "vec4 v0 = pD0;\n"); qstring_append(vars, "vec4 v1 = pD1;\n"); - qstring_append(vars, "float fog = pFog.x;\n"); ps->code = qstring_new(); From 5291bec473236126885afd7982b6d360f40576c9 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Mon, 27 Jul 2015 02:18:56 +0200 Subject: [PATCH 4/6] Fix vp fog + fog varying is a float now --- hw/xbox/nv2a_psh.c | 3 ++- hw/xbox/nv2a_shaders.c | 5 ++--- hw/xbox/nv2a_shaders_common.h | 2 +- hw/xbox/nv2a_vsh.c | 3 ++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/xbox/nv2a_psh.c b/hw/xbox/nv2a_psh.c index ae69c53d2d..c366a45127 100644 --- a/hw/xbox/nv2a_psh.c +++ b/hw/xbox/nv2a_psh.c @@ -539,6 +539,7 @@ static QString* psh_convert(struct PixelShader *ps) qstring_append(preflight, "\n"); qstring_append(preflight, "out vec4 fragColor;\n"); qstring_append(preflight, "\n"); + qstring_append(preflight, "uniform vec4 fogColor;\n"); /* calculate perspective-correct inputs */ QString *vars = qstring_new(); @@ -546,7 +547,7 @@ static QString* psh_convert(struct PixelShader *ps) qstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n"); - qstring_append(vars, "vec4 pFog = clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0);\n"); + qstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0));\n"); qstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n"); qstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n"); diff --git a/hw/xbox/nv2a_shaders.c b/hw/xbox/nv2a_shaders.c index e18940f8cd..1fc57e9964 100644 --- a/hw/xbox/nv2a_shaders.c +++ b/hw/xbox/nv2a_shaders.c @@ -329,12 +329,11 @@ static QString* generate_fixed_function(const ShaderState state, break; } /* FIXME: What about fog alpha?! */ - qstring_append(s, "vec4 tFog = vec4(fogColor.rgb, fogFactor);\n"); + qstring_append(s, "float tFog = fogFactor;\n"); } else { /* FIXME: Is the fog still calculated / passed somehow?! - * Maybe vec4(fogColor, fogCoord) ? */ - qstring_append(s, "vec4 tFog = vec4(0.0);\n"); + qstring_append(s, "float tFog = 0.0;\n"); } /* If skinning is off the composite matrix already includes the MV matrix */ diff --git a/hw/xbox/nv2a_shaders_common.h b/hw/xbox/nv2a_shaders_common.h index 19e0f88067..c8e1a962ff 100644 --- a/hw/xbox/nv2a_shaders_common.h +++ b/hw/xbox/nv2a_shaders_common.h @@ -27,7 +27,7 @@ " vec4 D1;\n" \ " vec4 B0;\n" \ " vec4 B1;\n" \ - " vec4 Fog;\n" \ + " float Fog;\n" \ " vec4 T0;\n" \ " vec4 T1;\n" \ " vec4 T2;\n" \ diff --git a/hw/xbox/nv2a_vsh.c b/hw/xbox/nv2a_vsh.c index 8313cddb75..3e43a284cc 100644 --- a/hw/xbox/nv2a_vsh.c +++ b/hw/xbox/nv2a_vsh.c @@ -737,6 +737,7 @@ QString* vsh_translate(uint16_t version, qstring_append(header, STRUCT_VERTEX_DATA); qstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n", out_prefix); qstring_append_fmt(header, "#define vtx %c_vtx", out_prefix); + qstring_append(header, "\n" "uniform mat4 texMat0;\n" "uniform mat4 texMat1;\n" @@ -780,7 +781,7 @@ QString* vsh_translate(uint16_t version, qstring_append(body, "vtx.D1 = clamp(oD1, 0.0, 1.0) * vtx.inv_w;\n"); qstring_append(body, "vtx.B0 = clamp(oB0, 0.0, 1.0) * vtx.inv_w;\n"); qstring_append(body, "vtx.B1 = clamp(oB1, 0.0, 1.0) * vtx.inv_w;\n"); - qstring_append(body, "vtx.Fog = oFog * vtx.inv_w;\n"); + qstring_append(body, "vtx.Fog = oFog.x * vtx.inv_w;\n"); qstring_append(body, "vtx.T0 = oT0 * vtx.inv_w;\n"); qstring_append(body, "vtx.T1 = oT1 * vtx.inv_w;\n"); qstring_append(body, "vtx.T2 = oT2 * vtx.inv_w;\n"); From 8ce4cf3dbc1f034bc420f4cadbd704d00d947574 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Tue, 28 Jul 2015 17:06:53 +0200 Subject: [PATCH 5/6] Use (experimental) formulas to get correct D3D fog --- hw/xbox/nv2a_shaders.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/hw/xbox/nv2a_shaders.c b/hw/xbox/nv2a_shaders.c index 1fc57e9964..2b63ed88d9 100644 --- a/hw/xbox/nv2a_shaders.c +++ b/hw/xbox/nv2a_shaders.c @@ -279,7 +279,7 @@ static QString* generate_fixed_function(const ShaderState state, break; case FOGGEN_PLANAR: case FOGGEN_ABS_PLANAR: - qstring_append(s, "float fogDistance = dot(fogPlane.xyz,tPosition.xyz)+fogPlane.w;\n"); + qstring_append(s, "float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n"); if (state.foggen == FOGGEN_ABS_PLANAR) { qstring_append(s, "fogDistance = abs(fogDistance);\n"); } @@ -298,21 +298,40 @@ static QString* generate_fixed_function(const ShaderState state, break; } + //FIXME: Do this per pixel? switch (state.fog_mode) { case FOG_MODE_LINEAR: case FOG_MODE_LINEAR_ABS: - qstring_append(s, "float fogFactor = fogDistance * fogParam[1] + fogParam[0];\n"); + + /* f = (end - d) / (end - start) + * fogParam[1] = 1 / (end - start) + * fogParam[0] = 1 + end * fogParam[1]; + */ + + qstring_append(s, "float fogFactor = fogParam[0] + fogDistance * fogParam[1];\n"); qstring_append(s, "fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */ break; case FOG_MODE_EXP: case FOG_MODE_EXP_ABS: - assert(false); /* FIXME: fogParam[0] and fogParam[0] ?? */ - qstring_append(s, "float fogFactor = exp(fogDistance);\n"); + + /* f = 1 / (e^(d * density)) + * fogParam[1] = -density / (2 * ln(256)) + * fogParam[0] = 1.5 + */ + + qstring_append(s, "float fogFactor = fogParam[0] + exp(fogDistance * fogParam[1] * 2.0 * 5.5452);\n"); + qstring_append(s, "fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */ break; case FOG_MODE_EXP2: case FOG_MODE_EXP2_ABS: - assert(false); /* FIXME: fogParam[0] and fogParam[0] ?? */ - qstring_append(s, "float fogFactor = exp(fogDistance * fogDistance);\n"); + + /* f = 1 / (e^((d * density)^2)) + * fogParam[1] = -density / (2 * sqrt(ln(256))) + * fogParam[0] = 1.5 + */ + + qstring_append(s, "float fogFactor = fogParam[0] + exp(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 4.0 * 5.5452);\n"); + qstring_append(s, "fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */ break; default: assert(false); From 4894aace0efdaed45f4ed5c2800053573ed08436 Mon Sep 17 00:00:00 2001 From: Jannik Vogel Date: Wed, 19 Aug 2015 18:48:30 +0200 Subject: [PATCH 6/6] Use EXP2 for fog to emulate hardware --- hw/xbox/nv2a_shaders.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a_shaders.c b/hw/xbox/nv2a_shaders.c index 2b63ed88d9..ce9d70e799 100644 --- a/hw/xbox/nv2a_shaders.c +++ b/hw/xbox/nv2a_shaders.c @@ -319,7 +319,7 @@ static QString* generate_fixed_function(const ShaderState state, * fogParam[0] = 1.5 */ - qstring_append(s, "float fogFactor = fogParam[0] + exp(fogDistance * fogParam[1] * 2.0 * 5.5452);\n"); + qstring_append(s, "float fogFactor = fogParam[0] + exp2(fogDistance * fogParam[1] * 16.0);\n"); qstring_append(s, "fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */ break; case FOG_MODE_EXP2: @@ -330,7 +330,7 @@ static QString* generate_fixed_function(const ShaderState state, * fogParam[0] = 1.5 */ - qstring_append(s, "float fogFactor = fogParam[0] + exp(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 4.0 * 5.5452);\n"); + qstring_append(s, "float fogFactor = fogParam[0] + exp2(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 32.0);\n"); qstring_append(s, "fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */ break; default: