diff --git a/Source/Core/VideoCommon/LightingShaderGen.cpp b/Source/Core/VideoCommon/LightingShaderGen.cpp index 5fa2c5b977..0cde653d25 100644 --- a/Source/Core/VideoCommon/LightingShaderGen.cpp +++ b/Source/Core/VideoCommon/LightingShaderGen.cpp @@ -17,60 +17,61 @@ static void GenerateLightShader(ShaderCode& object, const LightingUidData& uid_d const char* swizzle = alpha ? "a" : "rgb"; const char* swizzle_components = (alpha) ? "" : "3"; - int attnfunc = (uid_data.attnfunc >> (2 * litchan_index)) & 0x3; - int diffusefunc = (uid_data.diffusefunc >> (2 * litchan_index)) & 0x3; + const u32 attnfunc = (uid_data.attnfunc >> (2 * litchan_index)) & 0x3; + const u32 diffusefunc = (uid_data.diffusefunc >> (2 * litchan_index)) & 0x3; switch (attnfunc) { case LIGHTATTN_NONE: case LIGHTATTN_DIR: - object.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(index)); - object.Write("attn = 1.0;\n"); - object.Write("if (length(ldir) == 0.0)\n\t ldir = _norm0;\n"); + object.WriteFmt("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(index)); + object.WriteFmt("attn = 1.0;\n"); + object.WriteFmt("if (length(ldir) == 0.0)\n\t ldir = _norm0;\n"); break; case LIGHTATTN_SPEC: - object.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(index)); - object.Write("attn = (dot(_norm0, ldir) >= 0.0) ? max(0.0, dot(_norm0, " LIGHT_DIR - ".xyz)) : 0.0;\n", - LIGHT_DIR_PARAMS(index)); - object.Write("cosAttn = " LIGHT_COSATT ".xyz;\n", LIGHT_COSATT_PARAMS(index)); - object.Write("distAttn = %s(" LIGHT_DISTATT ".xyz);\n", - (diffusefunc == LIGHTDIF_NONE) ? "" : "normalize", LIGHT_DISTATT_PARAMS(index)); - object.Write("attn = max(0.0f, dot(cosAttn, float3(1.0, attn, attn*attn))) / dot(distAttn, " - "float3(1.0, attn, attn*attn));\n"); + object.WriteFmt("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(index)); + object.WriteFmt("attn = (dot(_norm0, ldir) >= 0.0) ? max(0.0, dot(_norm0, " LIGHT_DIR + ".xyz)) : 0.0;\n", + LIGHT_DIR_PARAMS(index)); + object.WriteFmt("cosAttn = " LIGHT_COSATT ".xyz;\n", LIGHT_COSATT_PARAMS(index)); + object.WriteFmt("distAttn = {}(" LIGHT_DISTATT ".xyz);\n", + (diffusefunc == LIGHTDIF_NONE) ? "" : "normalize", LIGHT_DISTATT_PARAMS(index)); + object.WriteFmt("attn = max(0.0f, dot(cosAttn, float3(1.0, attn, attn*attn))) / dot(distAttn, " + "float3(1.0, attn, attn*attn));\n"); break; case LIGHTATTN_SPOT: - object.Write("ldir = " LIGHT_POS ".xyz - pos.xyz;\n", LIGHT_POS_PARAMS(index)); - object.Write("dist2 = dot(ldir, ldir);\n" - "dist = sqrt(dist2);\n" - "ldir = ldir / dist;\n" - "attn = max(0.0, dot(ldir, " LIGHT_DIR ".xyz));\n", - LIGHT_DIR_PARAMS(index)); + object.WriteFmt("ldir = " LIGHT_POS ".xyz - pos.xyz;\n", LIGHT_POS_PARAMS(index)); + object.WriteFmt("dist2 = dot(ldir, ldir);\n" + "dist = sqrt(dist2);\n" + "ldir = ldir / dist;\n" + "attn = max(0.0, dot(ldir, " LIGHT_DIR ".xyz));\n", + LIGHT_DIR_PARAMS(index)); // attn*attn may overflow - object.Write("attn = max(0.0, " LIGHT_COSATT ".x + " LIGHT_COSATT ".y*attn + " LIGHT_COSATT - ".z*attn*attn) / dot(" LIGHT_DISTATT ".xyz, float3(1.0,dist,dist2));\n", - LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), - LIGHT_DISTATT_PARAMS(index)); + object.WriteFmt("attn = max(0.0, " LIGHT_COSATT ".x + " LIGHT_COSATT ".y*attn + " LIGHT_COSATT + ".z*attn*attn) / dot(" LIGHT_DISTATT ".xyz, float3(1.0,dist,dist2));\n", + LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), + LIGHT_COSATT_PARAMS(index), LIGHT_DISTATT_PARAMS(index)); break; } switch (diffusefunc) { case LIGHTDIF_NONE: - object.Write("lacc.%s += int%s(round(attn * float%s(" LIGHT_COL ")));\n", swizzle, - swizzle_components, swizzle_components, LIGHT_COL_PARAMS(index, swizzle)); + object.WriteFmt("lacc.{} += int{}(round(attn * float{}(" LIGHT_COL ")));\n", swizzle, + swizzle_components, swizzle_components, LIGHT_COL_PARAMS(index, swizzle)); break; case LIGHTDIF_SIGN: case LIGHTDIF_CLAMP: - object.Write("lacc.%s += int%s(round(attn * %sdot(ldir, _norm0)) * float%s(" LIGHT_COL ")));\n", - swizzle, swizzle_components, diffusefunc != LIGHTDIF_SIGN ? "max(0.0," : "(", - swizzle_components, LIGHT_COL_PARAMS(index, swizzle)); + object.WriteFmt("lacc.{} += int{}(round(attn * {}dot(ldir, _norm0)) * float{}(" LIGHT_COL + ")));\n", + swizzle, swizzle_components, diffusefunc != LIGHTDIF_SIGN ? "max(0.0," : "(", + swizzle_components, LIGHT_COL_PARAMS(index, swizzle)); break; default: ASSERT(0); } - object.Write("\n"); + object.WriteFmt("\n"); } // vertex shader @@ -79,127 +80,143 @@ static void GenerateLightShader(ShaderCode& object, const LightingUidData& uid_d // inColorName is color in vs and colors_ in ps // dest is o.colors_ in vs and colors_ in ps void GenerateLightingShaderCode(ShaderCode& object, const LightingUidData& uid_data, int components, - const char* inColorName, const char* dest) + std::string_view in_color_name, std::string_view dest) { - for (unsigned int j = 0; j < NUM_XF_COLOR_CHANNELS; j++) + for (u32 j = 0; j < NUM_XF_COLOR_CHANNELS; j++) { - object.Write("{\n"); + object.WriteFmt("{{\n"); - bool colormatsource = !!(uid_data.matsource & (1 << j)); + const bool colormatsource = !!(uid_data.matsource & (1 << j)); if (colormatsource) // from vertex { - if (components & (VB_HAS_COL0 << j)) - object.Write("int4 mat = int4(round(%s%d * 255.0));\n", inColorName, j); - else if (components & VB_HAS_COL0) - object.Write("int4 mat = int4(round(%s0 * 255.0));\n", inColorName); + if ((components & (VB_HAS_COL0 << j)) != 0) + object.WriteFmt("int4 mat = int4(round({}{} * 255.0));\n", in_color_name, j); + else if ((components & VB_HAS_COL0) != 0) + object.WriteFmt("int4 mat = int4(round({}0 * 255.0));\n", in_color_name); else - object.Write("int4 mat = int4(255, 255, 255, 255);\n"); + object.WriteFmt("int4 mat = int4(255, 255, 255, 255);\n"); } else // from color { - object.Write("int4 mat = %s[%d];\n", I_MATERIALS, j + 2); + object.WriteFmt("int4 mat = {}[{}];\n", I_MATERIALS, j + 2); } - if (uid_data.enablelighting & (1 << j)) + if ((uid_data.enablelighting & (1 << j)) != 0) { - if (uid_data.ambsource & (1 << j)) // from vertex + if ((uid_data.ambsource & (1 << j)) != 0) // from vertex { - if (components & (VB_HAS_COL0 << j)) - object.Write("lacc = int4(round(%s%d * 255.0));\n", inColorName, j); - else if (components & VB_HAS_COL0) - object.Write("lacc = int4(round(%s0 * 255.0));\n", inColorName); + if ((components & (VB_HAS_COL0 << j)) != 0) + { + object.WriteFmt("lacc = int4(round({}{} * 255.0));\n", in_color_name, j); + } + else if ((components & VB_HAS_COL0) != 0) + { + object.WriteFmt("lacc = int4(round({}0 * 255.0));\n", in_color_name); + } else + { // TODO: this isn't verified. Here we want to read the ambient from the vertex, // but the vertex itself has no color. So we don't know which value to read. // Returning 1.0 is the same as disabled lightning, so this could be fine - object.Write("lacc = int4(255, 255, 255, 255);\n"); + object.WriteFmt("lacc = int4(255, 255, 255, 255);\n"); + } } else // from color { - object.Write("lacc = %s[%d];\n", I_MATERIALS, j); + object.WriteFmt("lacc = {}[{}];\n", I_MATERIALS, j); } } else { - object.Write("lacc = int4(255, 255, 255, 255);\n"); + object.WriteFmt("lacc = int4(255, 255, 255, 255);\n"); } // check if alpha is different - bool alphamatsource = !!(uid_data.matsource & (1 << (j + 2))); + const bool alphamatsource = !!(uid_data.matsource & (1 << (j + 2))); if (alphamatsource != colormatsource) { if (alphamatsource) // from vertex { - if (components & (VB_HAS_COL0 << j)) - object.Write("mat.w = int(round(%s%d.w * 255.0));\n", inColorName, j); - else if (components & VB_HAS_COL0) - object.Write("mat.w = int(round(%s0.w * 255.0));\n", inColorName); + if ((components & (VB_HAS_COL0 << j)) != 0) + object.WriteFmt("mat.w = int(round({}{}.w * 255.0));\n", in_color_name, j); + else if ((components & VB_HAS_COL0) != 0) + object.WriteFmt("mat.w = int(round({}0.w * 255.0));\n", in_color_name); else - object.Write("mat.w = 255;\n"); + object.WriteFmt("mat.w = 255;\n"); } else // from color { - object.Write("mat.w = %s[%d].w;\n", I_MATERIALS, j + 2); + object.WriteFmt("mat.w = {}[{}].w;\n", I_MATERIALS, j + 2); } } - if (uid_data.enablelighting & (1 << (j + 2))) + if ((uid_data.enablelighting & (1 << (j + 2))) != 0) { - if (uid_data.ambsource & (1 << (j + 2))) // from vertex + if ((uid_data.ambsource & (1 << (j + 2))) != 0) // from vertex { - if (components & (VB_HAS_COL0 << j)) - object.Write("lacc.w = int(round(%s%d.w * 255.0));\n", inColorName, j); - else if (components & VB_HAS_COL0) - object.Write("lacc.w = int(round(%s0.w * 255.0));\n", inColorName); + if ((components & (VB_HAS_COL0 << j)) != 0) + { + object.WriteFmt("lacc.w = int(round({}{}.w * 255.0));\n", in_color_name, j); + } + else if ((components & VB_HAS_COL0) != 0) + { + object.WriteFmt("lacc.w = int(round({}0.w * 255.0));\n", in_color_name); + } else + { // TODO: The same for alpha: We want to read from vertex, but the vertex has no color - object.Write("lacc.w = 255;\n"); + object.WriteFmt("lacc.w = 255;\n"); + } } else // from color { - object.Write("lacc.w = %s[%d].w;\n", I_MATERIALS, j); + object.WriteFmt("lacc.w = {}[{}].w;\n", I_MATERIALS, j); } } else { - object.Write("lacc.w = 255;\n"); + object.WriteFmt("lacc.w = 255;\n"); } - if (uid_data.enablelighting & (1 << j)) // Color lights + if ((uid_data.enablelighting & (1 << j)) != 0) // Color lights { for (int i = 0; i < 8; ++i) - if (uid_data.light_mask & (1 << (i + 8 * j))) + { + if ((uid_data.light_mask & (1 << (i + 8 * j))) != 0) GenerateLightShader(object, uid_data, i, j, false); + } } - if (uid_data.enablelighting & (1 << (j + 2))) // Alpha lights + if ((uid_data.enablelighting & (1 << (j + 2))) != 0) // Alpha lights { for (int i = 0; i < 8; ++i) - if (uid_data.light_mask & (1 << (i + 8 * (j + 2)))) + { + if ((uid_data.light_mask & (1 << (i + 8 * (j + 2)))) != 0) GenerateLightShader(object, uid_data, i, j + 2, true); + } } - object.Write("lacc = clamp(lacc, 0, 255);\n"); - object.Write("%s%d = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n", dest, j); - object.Write("}\n"); + object.WriteFmt("lacc = clamp(lacc, 0, 255);\n"); + object.WriteFmt("{}{} = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n", dest, j); + object.WriteFmt("}}\n"); } } void GetLightingShaderUid(LightingUidData& uid_data) { - for (unsigned int j = 0; j < NUM_XF_COLOR_CHANNELS; j++) + for (u32 j = 0; j < NUM_XF_COLOR_CHANNELS; j++) { uid_data.matsource |= xfmem.color[j].matsource << j; uid_data.matsource |= xfmem.alpha[j].matsource << (j + 2); uid_data.enablelighting |= xfmem.color[j].enablelighting << j; uid_data.enablelighting |= xfmem.alpha[j].enablelighting << (j + 2); - if (uid_data.enablelighting & (1 << j)) // Color lights + if ((uid_data.enablelighting & (1 << j)) != 0) // Color lights { uid_data.ambsource |= xfmem.color[j].ambsource << j; uid_data.attnfunc |= xfmem.color[j].attnfunc << (2 * j); uid_data.diffusefunc |= xfmem.color[j].diffusefunc << (2 * j); uid_data.light_mask |= xfmem.color[j].GetFullLightMask() << (8 * j); } - if (uid_data.enablelighting & (1 << (j + 2))) // Alpha lights + if ((uid_data.enablelighting & (1 << (j + 2))) != 0) // Alpha lights { uid_data.ambsource |= xfmem.alpha[j].ambsource << (j + 2); uid_data.attnfunc |= xfmem.alpha[j].attnfunc << (2 * (j + 2)); diff --git a/Source/Core/VideoCommon/LightingShaderGen.h b/Source/Core/VideoCommon/LightingShaderGen.h index 096b5d10dd..437a463091 100644 --- a/Source/Core/VideoCommon/LightingShaderGen.h +++ b/Source/Core/VideoCommon/LightingShaderGen.h @@ -4,23 +4,24 @@ #pragma once +#include #include "Common/CommonTypes.h" class ShaderCode; -#define LIGHT_COL "%s[%d].color.%s" +#define LIGHT_COL "{}[{}].color.{}" #define LIGHT_COL_PARAMS(index, swizzle) (I_LIGHTS), (index), (swizzle) -#define LIGHT_COSATT "%s[%d].cosatt" +#define LIGHT_COSATT "{}[{}].cosatt" #define LIGHT_COSATT_PARAMS(index) (I_LIGHTS), (index) -#define LIGHT_DISTATT "%s[%d].distatt" +#define LIGHT_DISTATT "{}[{}].distatt" #define LIGHT_DISTATT_PARAMS(index) (I_LIGHTS), (index) -#define LIGHT_POS "%s[%d].pos" +#define LIGHT_POS "{}[{}].pos" #define LIGHT_POS_PARAMS(index) (I_LIGHTS), (index) -#define LIGHT_DIR "%s[%d].dir" +#define LIGHT_DIR "{}[{}].dir" #define LIGHT_DIR_PARAMS(index) (I_LIGHTS), (index) /** @@ -36,14 +37,14 @@ struct LightingUidData u32 light_mask : 32; // 4x8 bits }; -static const char s_lighting_struct[] = "struct Light {\n" - "\tint4 color;\n" - "\tfloat4 cosatt;\n" - "\tfloat4 distatt;\n" - "\tfloat4 pos;\n" - "\tfloat4 dir;\n" - "};\n"; +constexpr inline char s_lighting_struct[] = "struct Light {\n" + "\tint4 color;\n" + "\tfloat4 cosatt;\n" + "\tfloat4 distatt;\n" + "\tfloat4 pos;\n" + "\tfloat4 dir;\n" + "};\n"; void GenerateLightingShaderCode(ShaderCode& object, const LightingUidData& uid_data, int components, - const char* inColorName, const char* dest); + std::string_view in_color_name, std::string_view dest); void GetLightingShaderUid(LightingUidData& uid_data); diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 5fc6f7cee1..c4e04ff418 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -316,8 +316,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho if ((uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2)) != 0) { // transform the light dir into tangent space - out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", - LIGHT_POS_PARAMS(texinfo.embosslightshift)); + out.WriteFmt("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", + LIGHT_POS_PARAMS(texinfo.embosslightshift)); out.WriteFmt( "o.tex{}.xyz = o.tex{}.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0);\n", i, texinfo.embosssourceshift);