diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 96be41af09..fd13956eec 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -194,10 +194,9 @@ struct UB_VS_Bones { }; static const char *ub_vs_bonesStr = -R"( mat3x4 u_bone[8]; +R"( mat3x4 u_bone0; mat3x4 u_bone1; mat3x4 u_bone2; mat3x4 u_bone3; mat3x4 u_bone4; mat3x4 u_bone5; mat3x4 u_bone6; mat3x4 u_bone7; mat3x4 u_bone8; )"; -// HLSL code is shared so these names are changed to match those in DX9. static const char *cb_vs_bonesStr = R"( float4x3 u_bone[8]; )"; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 9a7d10e7ef..5d5af4f4a8 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -495,7 +495,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu float bonetemp[16]; for (int i = 0; i < numBones; i++) { if (dirty & (DIRTY_BONEMATRIX0 << i)) { - ConvertMatrix4x3To4x4(bonetemp, gstate.boneMatrix + 12 * i); + ConvertMatrix4x3To4x4Transposed(bonetemp, gstate.boneMatrix + 12 * i); render_->SetUniformM4x4(&u_bone[i], bonetemp); } } diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index c1916601e8..317c54fbd1 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -580,25 +580,14 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, const GLSLShade "w2.x", "w2.y", "w2.z", "w2.w", }; -#ifdef USE_BONE_ARRAY - if (numBoneWeights == 1) - WRITE(p, " mat4 skinMatrix = w1 * u_bone[0]"); - else - WRITE(p, " mat4 skinMatrix = w1.x * u_bone[0]"); - for (int i = 1; i < numBoneWeights; i++) { - const char *weightAttr = boneWeightAttr[i]; - // workaround for "cant do .x of scalar" issue - if (numBoneWeights == 1 && i == 0) weightAttr = "w1"; - if (numBoneWeights == 5 && i == 4) weightAttr = "w2"; - WRITE(p, " + %s * u_bone[%i]", weightAttr, i); - } -#else + const char *boneMatrix = compat.forceMatrix4x4 ? "mat4" : "mat3x4"; + // Uncomment this to screw up bone shaders to check the vertex shader software fallback // WRITE(p, "THIS SHOULD ERROR! #error"); if (numBoneWeights == 1) - WRITE(p, " mat4 skinMatrix = w1 * u_bone0"); + WRITE(p, " %s skinMatrix = w1 * u_bone0", boneMatrix); else - WRITE(p, " mat4 skinMatrix = w1.x * u_bone0"); + WRITE(p, " %s skinMatrix = w1.x * u_bone0", boneMatrix); for (int i = 1; i < numBoneWeights; i++) { const char *weightAttr = boneWeightAttr[i]; // workaround for "cant do .x of scalar" issue @@ -606,20 +595,18 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, const GLSLShade if (numBoneWeights == 5 && i == 4) weightAttr = "w2"; WRITE(p, " + %s * u_bone%i", weightAttr, i); } -#endif WRITE(p, ";\n"); - // Trying to simplify this results in bugs in LBP... - WRITE(p, " vec3 skinnedpos = (skinMatrix * vec4(position, 1.0)).xyz %s;\n", factor); - WRITE(p, " vec3 worldpos = (u_world * vec4(skinnedpos, 1.0)).xyz;\n"); + WRITE(p, " vec3 skinnedpos = (vec4(position, 1.0) * skinMatrix).xyz %s;\n", factor); + WRITE(p, " vec3 worldpos = (vec4(skinnedpos, 1.0) * u_world).xyz;\n"); if (hasNormal) { - WRITE(p, " mediump vec3 skinnednormal = (skinMatrix * vec4(%snormal, 0.0)).xyz %s;\n", flipNormal ? "-" : "", factor); + WRITE(p, " mediump vec3 skinnednormal = (vec4(%snormal, 0.0) * skinMatrix).xyz %s;\n", flipNormal ? "-" : "", factor); } else { - WRITE(p, " mediump vec3 skinnednormal = (skinMatrix * vec4(0.0, 0.0, %s1.0, 0.0)).xyz %s;\n", flipNormal ? "-" : "", factor); + WRITE(p, " mediump vec3 skinnednormal = (vec4(0.0, 0.0, %s1.0, 0.0) * skinMatrix).xyz %s;\n", flipNormal ? "-" : "", factor); } - WRITE(p, " mediump vec3 worldnormal = normalize((u_world * vec4(skinnednormal, 0.0)).xyz);\n"); + WRITE(p, " mediump vec3 worldnormal = normalize((vec4(skinnednormal, 0.0) * u_world).xyz);\n"); } WRITE(p, " vec4 viewPos = vec4((vec4(worldpos, 1.0) * u_view).xyz, 1.0);\n"); diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 22613b0594..cb295d4f6a 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -361,25 +361,24 @@ bool GenerateVertexShaderVulkanGLSL(const VShaderID &id, char *buffer, std::stri "w2.x", "w2.y", "w2.z", "w2.w", }; - WRITE(p, " mat3x4 skinMatrix = w1.x * u_bone[0];\n"); + WRITE(p, " mat3x4 skinMatrix = w1.x * u_bone0"); if (numBoneWeights > 1) { for (int i = 1; i < numBoneWeights; i++) { - WRITE(p, " skinMatrix += %s * u_bone[%i];\n", boneWeightAttr[i], i); + WRITE(p, " + %s * u_bone%d", boneWeightAttr[i], i); } } WRITE(p, ";\n"); - // Trying to simplify this results in bugs in LBP... - WRITE(p, " vec3 skinnedpos = (vec4(position, 1.0) * skinMatrix) %s;\n", factor); - WRITE(p, " vec3 worldpos = vec4(skinnedpos, 1.0) * u_world;\n"); + WRITE(p, " vec3 skinnedpos = (vec4(position, 1.0) * skinMatrix).xyz %s;\n", factor); + WRITE(p, " vec3 worldpos = (vec4(skinnedpos, 1.0) * u_world).xyz;\n"); if (hasNormal) { - WRITE(p, " mediump vec3 skinnednormal = vec4(%snormal, 0.0) * skinMatrix %s;\n", flipNormal ? "-" : "", factor); + WRITE(p, " mediump vec3 skinnednormal = (vec4(%snormal, 0.0) * skinMatrix).xyz %s;\n", flipNormal ? "-" : "", factor); } else { - WRITE(p, " mediump vec3 skinnednormal = vec4(0.0, 0.0, %s1.0, 0.0) * skinMatrix %s;\n", flipNormal ? "-" : "", factor); + WRITE(p, " mediump vec3 skinnednormal = (vec4(0.0, 0.0, %s1.0, 0.0) * skinMatrix).xyz %s;\n", flipNormal ? "-" : "", factor); } - WRITE(p, " mediump vec3 worldnormal = normalize(vec4(skinnednormal, 0.0) * u_world);\n"); + WRITE(p, " mediump vec3 worldnormal = normalize((vec4(skinnednormal, 0.0) * u_world).xyz);\n"); } WRITE(p, " vec4 viewPos = vec4((vec4(worldpos, 1.0) * u_view).xyz, 1.0);\n"); @@ -408,7 +407,7 @@ bool GenerateVertexShaderVulkanGLSL(const VShaderID &id, char *buffer, std::stri bool distanceNeeded = false; if (enableLighting) { - WRITE(p, " vec4 lightSum0 = u_ambient * %s + vec4(u_matemissive, 0.0);\n", ambientStr); + WRITE(p, " lowp vec4 lightSum0 = u_ambient * %s + vec4(u_matemissive, 0.0);\n", ambientStr); for (int i = 0; i < 4; i++) { GELightType type = static_cast(id.Bits(VS_BIT_LIGHT0_TYPE + 4 * i, 2));