GPU: Normalize 0 to 1 always in software lighting.

See #14167.  This seems to be consistent.
This commit is contained in:
Unknown W. Brackets 2021-02-27 23:51:45 -08:00
parent 5d4d8ab418
commit 2f63f9999d
6 changed files with 50 additions and 20 deletions

View File

@ -17,6 +17,7 @@
#include <algorithm>
#include <cmath>
#include "Common/CPUDetect.h"
#include "Common/Math/math_util.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
@ -266,7 +267,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
normal = -normal;
}
Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix);
worldnormal = worldnormal.Normalized();
worldnormal = worldnormal.NormalizedOr001(cpu_info.bSSE4_1);
}
} else {
float weights[8];
@ -298,7 +299,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
normal = -normal;
}
Norm3ByMatrix43(worldnormal.AsArray(), normal.AsArray(), gstate.worldMatrix);
worldnormal = worldnormal.Normalized();
worldnormal = worldnormal.NormalizedOr001(cpu_info.bSSE4_1);
}
}
@ -358,7 +359,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
break;
case GE_PROJMAP_NORMALIZED_NORMAL: // Use normalized normal as source
source = normal.Normalized();
source = normal.NormalizedOr001(cpu_info.bSSE4_1);
if (!reader.hasNormal()) {
ERROR_LOG_REPORT(G3D, "Normal projection mapping without normal?");
}
@ -391,11 +392,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
};
auto calcShadingLPos = [&](int l) {
Vec3f pos = getLPos(l);
if (pos.Length2() == 0.0f) {
return Vec3f(0.0f, 0.0f, 1.0f);
} else {
return pos.Normalized();
}
return pos.NormalizedOr001(cpu_info.bSSE4_1);
};
// Might not have lighting enabled, so don't use lighter.
Vec3f lightpos0 = calcShadingLPos(gstate.getUVLS0());

View File

@ -17,6 +17,7 @@
#include <stdio.h>
#include "Common/CPUDetect.h"
#include "GPU/GPUState.h"
#include "GPU/Common/TransformCommon.h"
@ -140,7 +141,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
case GE_LIGHTTYPE_SPOT:
case GE_LIGHTTYPE_UNKNOWN:
lightDir = Vec3Packedf(&ldir[l * 3]);
angle = Dot(toLight.Normalized(), lightDir.Normalized());
angle = Dot(toLight.NormalizedOr001(cpu_info.bSSE4_1), lightDir.NormalizedOr001(cpu_info.bSSE4_1));
if (angle >= lcutoff[l])
lightScale = clamp(1.0f / (latt[l * 3] + latt[l * 3 + 1] * distanceToLight + latt[l * 3 + 2] * distanceToLight*distanceToLight), 0.0f, 1.0f) * powf(angle, lconv[l]);
break;
@ -155,11 +156,10 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
// Real PSP specular
Vec3f toViewer(0, 0, 1);
// Better specular
// Vec3f toViewer = (viewer - pos).Normalized();
// Vec3f toViewer = (viewer - pos).NormalizedOr001(cpu_info.bSSE4_1);
if (doSpecular) {
Vec3f halfVec = (toLight + toViewer);
halfVec.Normalize();
Vec3f halfVec = (toLight + toViewer).NormalizedOr001(cpu_info.bSSE4_1);
dot = Dot(halfVec, norm);
if (dot > 0.0f) {

View File

@ -138,12 +138,31 @@ Vec3<float> Vec3<float>::Normalized(bool useSSE4) const
const __m128 normalize = SSENormalizeMultiplier(useSSE4, vec);
return _mm_mul_ps(normalize, vec);
}
template<>
Vec3<float> Vec3<float>::NormalizedOr001(bool useSSE4) const {
const __m128 normalize = SSENormalizeMultiplier(useSSE4, vec);
const __m128 result = _mm_mul_ps(normalize, vec);
const __m128 mask = _mm_cmpunord_ps(result, vec);
const __m128 replace = _mm_and_ps(_mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f), mask);
// Replace with the constant if the mask matched.
return _mm_or_ps(_mm_andnot_ps(mask, result), replace);
}
#else
template<>
Vec3<float> Vec3<float>::Normalized(bool useSSE4) const
{
return (*this) / Length();
}
template<>
Vec3<float> Vec3<float>::NormalizedOr001(bool useSSE4) const {
float len = Length();
if (len == 0.0f) {
return Vec3<float>(0.0f, 0.0f, 1.0f);
}
return *this / len;
}
#endif
template<>
@ -154,6 +173,17 @@ float Vec3<float>::Normalize()
return len;
}
template<>
float Vec3<float>::NormalizeOr001() {
float len = Length();
if (len == 0.0f) {
z = 1.0f;
} else {
*this /= len;
}
return len;
}
template<>
Vec3Packed<float> Vec3Packed<float>::FromRGB(unsigned int rgb)
{

View File

@ -297,7 +297,9 @@ public:
Vec3 WithLength(const float l) const;
float Distance2To(Vec3 &other);
Vec3 Normalized(bool useSSE4 = false) const;
Vec3 NormalizedOr001(bool useSSE4 = false) const;
float Normalize(); // returns the previous length, which is often useful
float NormalizeOr001();
T& operator [] (int i) //allow vector[2] = 3 (vector.z=3)
{

View File

@ -15,9 +15,9 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "../GPUState.h"
#include "Lighting.h"
#include "Common/CPUDetect.h"
#include "GPU/GPUState.h"
#include "GPU/Software/Lighting.h"
namespace Lighting {
@ -53,7 +53,7 @@ void Process(VertexData& vertex, bool hasColor) {
if (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP) {
Vec3<float> L = GetLightVec(gstate.lpos, light);
// In other words, L.Length2() == 0.0f means Dot({0, 0, 1}, worldnormal).
float diffuse_factor = L.Length2() == 0.0f ? vertex.worldnormal.z : Dot(L.Normalized(), vertex.worldnormal);
float diffuse_factor = Dot(L.NormalizedOr001(cpu_info.bSSE4_1), vertex.worldnormal);
if (gstate.getUVLS0() == (int)light)
vertex.texturecoords.s() = (diffuse_factor + 1.f) / 2.f;
@ -77,7 +77,7 @@ void Process(VertexData& vertex, bool hasColor) {
L -= vertex.worldpos;
}
// TODO: Should this normalize (0, 0, 0) to (0, 0, 1)?
float d = L.Normalize();
float d = L.NormalizeOr001();
float att = 1.f;
if (!gstate.isDirectionalLight(light)) {
@ -89,7 +89,7 @@ void Process(VertexData& vertex, bool hasColor) {
float spot = 1.f;
if (gstate.isSpotLight(light)) {
Vec3<float> dir = GetLightVec(gstate.ldir, light);
float rawSpot = dir.Length2() == 0.0f ? 0.0f : Dot(dir.Normalized(), L);
float rawSpot = Dot(dir.NormalizedOr001(cpu_info.bSSE4_1), L);
float cutoff = getFloat24(gstate.lcutoff[light]);
if (rawSpot >= cutoff) {
float conv = getFloat24(gstate.lconv[light]);
@ -123,7 +123,7 @@ void Process(VertexData& vertex, bool hasColor) {
Vec3<float> lsc = Vec3<float>::FromRGB(gstate.getSpecularColor(light));
Vec3<float> msc = (materialupdate & 4) ? vcol0 : Vec3<float>::FromRGB(gstate.getMaterialSpecular());
float specular_factor = Dot(H.Normalized(), vertex.worldnormal);
float specular_factor = Dot(H.NormalizedOr001(cpu_info.bSSE4_1), vertex.worldnormal);
float k = gstate.getMaterialSpecularCoef();
specular_factor = pspLightPow(specular_factor, k);

View File

@ -18,6 +18,7 @@
#include <cmath>
#include <algorithm>
#include "Common/CPUDetect.h"
#include "Common/Math/math_util.h"
#include "Common/MemoryUtil.h"
#include "Core/Config.h"
@ -256,7 +257,7 @@ VertexData TransformUnit::ReadVertex(VertexReader& vreader)
break;
case GE_PROJMAP_NORMALIZED_NORMAL:
source = vertex.normal.Normalized();
source = vertex.normal.NormalizedOr001(cpu_info.bSSE4_1);
break;
case GE_PROJMAP_NORMAL: