From 88134a6786b102dbb9b473fa42d748ae9c64af91 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Tue, 28 Dec 2021 13:01:57 -0800 Subject: VertexShaderGen: Simplify normal calculation This is a readability change; there should be no functional or performance differences. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 75 +++++++++++++---------------- 1 file changed, 34 insertions(+), 41 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 7f3e00609a..b00c8017e1 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -222,60 +222,53 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho // transforms if ((uid_data->components & VB_HAS_POSMTXIDX) != 0) { + // Vertex format has a per-vertex matrix out.Write("int posidx = int(posmtx.r);\n" - "float4 pos = float4(dot(" I_TRANSFORMMATRICES - "[posidx], rawpos), dot(" I_TRANSFORMMATRICES - "[posidx+1], rawpos), dot(" I_TRANSFORMMATRICES "[posidx+2], rawpos), 1);\n"); - + "float4 P0 = " I_TRANSFORMMATRICES "[posidx];\n" + "float4 P1 = " I_TRANSFORMMATRICES "[posidx + 1];\n" + "float4 P2 = " I_TRANSFORMMATRICES "[posidx + 2];\n"); if ((uid_data->components & VB_HAS_NRMALL) != 0) { out.Write("int normidx = posidx & 31;\n" - "float3 N0 = " I_NORMALMATRICES "[normidx].xyz, N1 = " I_NORMALMATRICES - "[normidx+1].xyz, N2 = " I_NORMALMATRICES "[normidx+2].xyz;\n"); - } - - if ((uid_data->components & VB_HAS_NRM0) != 0) - { - out.Write("float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, " - "rawnorm0)));\n"); - } - if ((uid_data->components & VB_HAS_NRM1) != 0) - { - out.Write( - "float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n"); - } - if ((uid_data->components & VB_HAS_NRM2) != 0) - { - out.Write( - "float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n"); + "float3 N0 = " I_NORMALMATRICES "[normidx].xyz;\n" + "float3 N1 = " I_NORMALMATRICES "[normidx + 1].xyz;\n" + "float3 N2 = " I_NORMALMATRICES "[normidx + 2].xyz;\n"); } } else { - out.Write("float4 pos = float4(dot(" I_POSNORMALMATRIX "[0], rawpos), dot(" I_POSNORMALMATRIX - "[1], rawpos), dot(" I_POSNORMALMATRIX "[2], rawpos), 1.0);\n"); - if ((uid_data->components & VB_HAS_NRM0) != 0) - { - out.Write("float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX - "[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX - "[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm0)));\n"); - } - if ((uid_data->components & VB_HAS_NRM1) != 0) - { - out.Write("float3 _norm1 = float3(dot(" I_POSNORMALMATRIX - "[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX - "[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm1));\n"); - } - if ((uid_data->components & VB_HAS_NRM2) != 0) + // One shared matrix + out.Write("float4 P0 = " I_POSNORMALMATRIX "[0];\n" + "float4 P1 = " I_POSNORMALMATRIX "[1];\n" + "float4 P2 = " I_POSNORMALMATRIX "[2];\n"); + if ((uid_data->components & VB_HAS_NRMALL) != 0) { - out.Write("float3 _norm2 = float3(dot(" I_POSNORMALMATRIX - "[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX - "[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm2));\n"); + out.Write("float3 N0 = " I_POSNORMALMATRIX "[3].xyz;\n" + "float3 N1 = " I_POSNORMALMATRIX "[4].xyz;\n" + "float3 N2 = " I_POSNORMALMATRIX "[5].xyz;\n"); } } - if ((uid_data->components & VB_HAS_NRM0) == 0) + out.Write("// Multiply the position vector by the position matrix\n" + "float4 pos = float4(dot(P0, rawpos), dot(P1, rawpos), dot(P2, rawpos), 1.0);\n"); + if ((uid_data->components & VB_HAS_NRM0) != 0) + { + // Only the first normal gets normalized (TODO: why?) + out.Write("float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, " + "rawnorm0)));\n"); + } + else + { out.Write("float3 _norm0 = float3(0.0, 0.0, 0.0);\n"); + } + if ((uid_data->components & VB_HAS_NRM1) != 0) + { + out.Write("float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n"); + } + if ((uid_data->components & VB_HAS_NRM2) != 0) + { + out.Write("float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n"); + } out.Write("o.pos = float4(dot(" I_PROJECTION "[0], pos), dot(" I_PROJECTION "[1], pos), dot(" I_PROJECTION "[2], pos), dot(" I_PROJECTION "[3], pos));\n"); -- cgit v1.2.3 From 04fdadd9d5f9588055fb54571410febfa710b86d Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Fri, 22 Apr 2022 12:50:44 -0700 Subject: VideoCommon: Rename norm0/norm1/norm2 to normal/tangent/binormal --- Source/Core/VideoCommon/VertexShaderGen.cpp | 68 +++++++++++++++-------------- 1 file changed, 35 insertions(+), 33 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index b00c8017e1..50ef13a9d7 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -39,7 +39,7 @@ VertexShaderUid GetVertexShaderUid() switch (texinfo.texgentype) { case TexGenType::EmbossMap: // calculate tex coords into bump map - if ((uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2)) != 0) + if ((uid_data->components & (VB_HAS_TANGENT | VB_HAS_BINORMAL)) != 0) { // transform the light dir into tangent space texinfo.embosslightshift = xfmem.texMtxInfo[i].embosslightshift; @@ -105,12 +105,12 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho out.Write("ATTRIBUTE_LOCATION({}) in float4 rawpos;\n", SHADER_POSITION_ATTRIB); if ((uid_data->components & VB_HAS_POSMTXIDX) != 0) out.Write("ATTRIBUTE_LOCATION({}) in uint4 posmtx;\n", SHADER_POSMTX_ATTRIB); - if ((uid_data->components & VB_HAS_NRM0) != 0) - out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnorm0;\n", SHADER_NORM0_ATTRIB); - if ((uid_data->components & VB_HAS_NRM1) != 0) - out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnorm1;\n", SHADER_NORM1_ATTRIB); - if ((uid_data->components & VB_HAS_NRM2) != 0) - out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnorm2;\n", SHADER_NORM2_ATTRIB); + if ((uid_data->components & VB_HAS_NORMAL) != 0) + out.Write("ATTRIBUTE_LOCATION({}) in float3 rawnormal;\n", SHADER_NORMAL_ATTRIB); + if ((uid_data->components & VB_HAS_TANGENT) != 0) + out.Write("ATTRIBUTE_LOCATION({}) in float3 rawtangent;\n", SHADER_TANGENT_ATTRIB); + if ((uid_data->components & VB_HAS_BINORMAL) != 0) + out.Write("ATTRIBUTE_LOCATION({}) in float3 rawbinormal;\n", SHADER_BINORMAL_ATTRIB); if ((uid_data->components & VB_HAS_COL0) != 0) out.Write("ATTRIBUTE_LOCATION({}) in float4 rawcolor0;\n", SHADER_COLOR0_ATTRIB); @@ -169,12 +169,12 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho out.Write("VS_OUTPUT main(\n"); // inputs - if ((uid_data->components & VB_HAS_NRM0) != 0) - out.Write(" float3 rawnorm0 : NORMAL0,\n"); - if ((uid_data->components & VB_HAS_NRM1) != 0) - out.Write(" float3 rawnorm1 : NORMAL1,\n"); - if ((uid_data->components & VB_HAS_NRM2) != 0) - out.Write(" float3 rawnorm2 : NORMAL2,\n"); + if ((uid_data->components & VB_HAS_NORMAL) != 0) + out.Write(" float3 rawnormal : NORMAL,\n"); + if ((uid_data->components & VB_HAS_TANGENT) != 0) + out.Write(" float3 rawtangent : TANGENT,\n"); + if ((uid_data->components & VB_HAS_BINORMAL) != 0) + out.Write(" float3 rawbinormal : BINORMAL,\n"); if ((uid_data->components & VB_HAS_COL0) != 0) out.Write(" float4 rawcolor0 : COLOR0,\n"); if ((uid_data->components & VB_HAS_COL1) != 0) @@ -227,7 +227,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho "float4 P0 = " I_TRANSFORMMATRICES "[posidx];\n" "float4 P1 = " I_TRANSFORMMATRICES "[posidx + 1];\n" "float4 P2 = " I_TRANSFORMMATRICES "[posidx + 2];\n"); - if ((uid_data->components & VB_HAS_NRMALL) != 0) + if ((uid_data->components & VB_HAS_NORMAL) != 0) { out.Write("int normidx = posidx & 31;\n" "float3 N0 = " I_NORMALMATRICES "[normidx].xyz;\n" @@ -241,7 +241,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho out.Write("float4 P0 = " I_POSNORMALMATRIX "[0];\n" "float4 P1 = " I_POSNORMALMATRIX "[1];\n" "float4 P2 = " I_POSNORMALMATRIX "[2];\n"); - if ((uid_data->components & VB_HAS_NRMALL) != 0) + if ((uid_data->components & VB_HAS_NORMAL) != 0) { out.Write("float3 N0 = " I_POSNORMALMATRIX "[3].xyz;\n" "float3 N1 = " I_POSNORMALMATRIX "[4].xyz;\n" @@ -251,23 +251,25 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho out.Write("// Multiply the position vector by the position matrix\n" "float4 pos = float4(dot(P0, rawpos), dot(P1, rawpos), dot(P2, rawpos), 1.0);\n"); - if ((uid_data->components & VB_HAS_NRM0) != 0) + if ((uid_data->components & VB_HAS_NORMAL) != 0) { // Only the first normal gets normalized (TODO: why?) - out.Write("float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, " - "rawnorm0)));\n"); + out.Write("float3 _normal = normalize(float3(dot(N0, rawnormal), dot(N1, rawnormal), dot(N2, " + "rawnormal)));\n"); } else { - out.Write("float3 _norm0 = float3(0.0, 0.0, 0.0);\n"); + out.Write("float3 _normal = float3(0.0, 0.0, 0.0);\n"); } - if ((uid_data->components & VB_HAS_NRM1) != 0) + if ((uid_data->components & VB_HAS_TANGENT) != 0) { - out.Write("float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n"); + out.Write("float3 _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, " + "rawtangent));\n"); } - if ((uid_data->components & VB_HAS_NRM2) != 0) + if ((uid_data->components & VB_HAS_BINORMAL) != 0) { - out.Write("float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n"); + out.Write("float3 _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, " + "rawbinormal));\n"); } out.Write("o.pos = float4(dot(" I_PROJECTION "[0], pos), dot(" I_PROJECTION @@ -293,24 +295,24 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho out.Write("coord.xyz = rawpos.xyz;\n"); break; case SourceRow::Normal: - if ((uid_data->components & VB_HAS_NRM0) != 0) + if ((uid_data->components & VB_HAS_NORMAL) != 0) { - out.Write("coord.xyz = rawnorm0.xyz;\n"); + out.Write("coord.xyz = rawnormal.xyz;\n"); } break; case SourceRow::Colors: ASSERT(texinfo.texgentype == TexGenType::Color0 || texinfo.texgentype == TexGenType::Color1); break; case SourceRow::BinormalT: - if ((uid_data->components & VB_HAS_NRM1) != 0) + if ((uid_data->components & VB_HAS_TANGENT) != 0) { - out.Write("coord.xyz = rawnorm1.xyz;\n"); + out.Write("coord.xyz = rawtangent.xyz;\n"); } break; case SourceRow::BinormalB: - if ((uid_data->components & VB_HAS_NRM2) != 0) + if ((uid_data->components & VB_HAS_BINORMAL) != 0) { - out.Write("coord.xyz = rawnorm2.xyz;\n"); + out.Write("coord.xyz = rawbinormal.xyz;\n"); } break; default: @@ -339,14 +341,14 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho { case TexGenType::EmbossMap: // calculate tex coords into bump map - if ((uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2)) != 0) + if ((uid_data->components & (VB_HAS_TANGENT | VB_HAS_BINORMAL)) != 0) { // transform the light dir into tangent space out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(texinfo.embosslightshift)); out.Write( - "o.tex{}.xyz = o.tex{}.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0);\n", i, - texinfo.embosssourceshift); + "o.tex{}.xyz = o.tex{}.xyz + float3(dot(ldir, _tangent), dot(ldir, _binormal), 0.0);\n", + i, texinfo.embosssourceshift); } else { @@ -464,7 +466,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho if (per_pixel_lighting) { - out.Write("o.Normal = _norm0;\n" + out.Write("o.Normal = _normal;\n" "o.WorldPos = pos.xyz;\n"); } -- cgit v1.2.3 From 2a5c77f43ff1d69e78f12f13435a38c5eb2ed854 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Wed, 13 Apr 2022 22:03:34 -0700 Subject: VideoCommon: Handle emboss texgen with only a single normal Fixes a large number of effects in Rogue Squadron 2 and 3. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 45 ++++++++++++----------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 50ef13a9d7..0b176386e9 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -253,23 +253,24 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho "float4 pos = float4(dot(P0, rawpos), dot(P1, rawpos), dot(P2, rawpos), 1.0);\n"); if ((uid_data->components & VB_HAS_NORMAL) != 0) { + if ((uid_data->components & VB_HAS_TANGENT) == 0) + out.Write("float3 rawtangent = " I_CACHED_TANGENT ".xyz;\n"); + if ((uid_data->components & VB_HAS_BINORMAL) == 0) + out.Write("float3 rawbinormal = " I_CACHED_BINORMAL ".xyz;\n"); + // Only the first normal gets normalized (TODO: why?) out.Write("float3 _normal = normalize(float3(dot(N0, rawnormal), dot(N1, rawnormal), dot(N2, " - "rawnormal)));\n"); + "rawnormal)));\n" + "float3 _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, " + "rawtangent));\n" + "float3 _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, " + "rawbinormal));\n"); } else { out.Write("float3 _normal = float3(0.0, 0.0, 0.0);\n"); - } - if ((uid_data->components & VB_HAS_TANGENT) != 0) - { - out.Write("float3 _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, " - "rawtangent));\n"); - } - if ((uid_data->components & VB_HAS_BINORMAL) != 0) - { - out.Write("float3 _binormal = float3(dot(N0, rawbinormal), dot(N1, rawbinormal), dot(N2, " - "rawbinormal));\n"); + out.Write("float3 _binormal = float3(0.0, 0.0, 0.0);\n"); + out.Write("float3 _tangent = float3(0.0, 0.0, 0.0);\n"); } out.Write("o.pos = float4(dot(" I_PROJECTION "[0], pos), dot(" I_PROJECTION @@ -341,22 +342,12 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho { case TexGenType::EmbossMap: // calculate tex coords into bump map - if ((uid_data->components & (VB_HAS_TANGENT | VB_HAS_BINORMAL)) != 0) - { - // transform the light dir into tangent space - out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", - LIGHT_POS_PARAMS(texinfo.embosslightshift)); - out.Write( - "o.tex{}.xyz = o.tex{}.xyz + float3(dot(ldir, _tangent), dot(ldir, _binormal), 0.0);\n", - i, texinfo.embosssourceshift); - } - else - { - // The following assert was triggered in House of the Dead Overkill and Star Wars Rogue - // Squadron 2 - // ASSERT(0); // should have normals - out.Write("o.tex{}.xyz = o.tex{}.xyz;\n", i, texinfo.embosssourceshift); - } + // transform the light dir into tangent space + out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", + LIGHT_POS_PARAMS(texinfo.embosslightshift)); + out.Write( + "o.tex{}.xyz = o.tex{}.xyz + float3(dot(ldir, _tangent), dot(ldir, _binormal), 0.0);\n", + i, texinfo.embosssourceshift); break; case TexGenType::Color0: -- cgit v1.2.3 From 784079853d9daa4d5e4de0b49b610ec0e58a2b0c Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Tue, 19 Apr 2022 17:46:20 -0700 Subject: VideoCommon: Add comment explaining why only the first normal gets normalized Co-authored-by: Scott Mansell --- Source/Core/VideoCommon/VertexShaderGen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 0b176386e9..9fa2d6cd0e 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -258,7 +258,11 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho if ((uid_data->components & VB_HAS_BINORMAL) == 0) out.Write("float3 rawbinormal = " I_CACHED_BINORMAL ".xyz;\n"); - // Only the first normal gets normalized (TODO: why?) + // The scale of the transform matrix is used to control the size of the emboss map effect, by + // changing the scale of the transformed binormals (which only get used by emboss map texgens). + // By normalising the first transformed normal (which is used by lighting calculations and needs + // to be unit length), the same transform matrix can do double duty, scaling for emboss mapping, + // and not scaling for lighting. out.Write("float3 _normal = normalize(float3(dot(N0, rawnormal), dot(N1, rawnormal), dot(N2, " "rawnormal)));\n" "float3 _tangent = float3(dot(N0, rawtangent), dot(N1, rawtangent), dot(N2, " -- cgit v1.2.3