GFX3D: Clean up some lighting-related code.

This commit is contained in:
rogerman 2023-02-16 02:59:05 -08:00
parent 79aa5b558e
commit db365e849f
1 changed files with 83 additions and 61 deletions

View File

@ -302,11 +302,9 @@ static u8 _shininessTableCurrentIndex = 0;
int freelookMode = 0;
s32 freelookMatrix[16];
//-----------cached things:
//these dont need to go into the savestate. they can be regenerated from HW registers
//from polygonattr:
static CACHE_ALIGN Vector32x4 _cacheLightDirection[4];
static CACHE_ALIGN Vector32x4 _cacheHalfVector[4];
static CACHE_ALIGN Vector32x4 _vecLightDirectionTransformed[4];
static CACHE_ALIGN Vector32x4 _vecLightDirectionHalfNegative[4];
static bool _doesLightHalfVectorNeedUpdate[4];
//------------------
#define RENDER_FRONT_SURFACE 0x80
@ -484,6 +482,16 @@ void gfx3d_reset()
mtxStackIndex[MATRIXMODE_POSITION] = 0;
mtxStackIndex[MATRIXMODE_POSITION_VECTOR] = 0;
mtxStackIndex[MATRIXMODE_TEXTURE] = 0;
_regLightDirection[0] = 0;
_regLightDirection[1] = 0;
_regLightDirection[2] = 0;
_regLightDirection[3] = 0;
memset(&_vecLightDirectionTransformed[0], 0, sizeof(Vector32x4) * 4);
_doesLightHalfVectorNeedUpdate[0] = true;
_doesLightHalfVectorNeedUpdate[1] = true;
_doesLightHalfVectorNeedUpdate[2] = true;
_doesLightHalfVectorNeedUpdate[3] = true;
_BTind = 0;
_PTind = 0;
@ -1811,27 +1819,21 @@ void NDSGeometryEngine::LoadState(const GeometryEngineLegacySave &inLegacySave)
this->SetViewport(inLegacySave.regViewport);
}
static void gfx3d_glLightDirection_cache(const size_t index)
static void gfx3d_UpdateLightDirectionHalfAngleVector(const size_t index)
{
const u32 v = _regLightDirection[index];
_cacheLightDirection[index].x = ((s32)((v<<22) & 0xFFC00000) / (s32)(1<<22)) * (s32)(1<<3);
_cacheLightDirection[index].y = ((s32)((v<<12) & 0xFFC00000) / (s32)(1<<22)) * (s32)(1<<3);
_cacheLightDirection[index].z = ((s32)((v<< 2) & 0xFFC00000) / (s32)(1<<22)) * (s32)(1<<3);
_cacheLightDirection[index].w = 0;
//Multiply the vector by the directional matrix
MatrixMultVec3x3(_mtxCurrent[MATRIXMODE_POSITION_VECTOR], _cacheLightDirection[index].vec);
//Calculate the half angle vector
CACHE_ALIGN const Vector32x4 lineOfSight = {0, 0, (s32)0xFFFFF000, 0};
_cacheHalfVector[index].x = _cacheLightDirection[index].x + lineOfSight.x;
_cacheHalfVector[index].y = _cacheLightDirection[index].y + lineOfSight.y;
_cacheHalfVector[index].z = _cacheLightDirection[index].z + lineOfSight.z;
_cacheHalfVector[index].w = _cacheLightDirection[index].w + lineOfSight.w;
CACHE_ALIGN static const Vector32x4 lineOfSight = {0, 0, (s32)0xFFFFF000, 0};
Vector32x4 half = {
_vecLightDirectionTransformed[index].x + lineOfSight.x,
_vecLightDirectionTransformed[index].y + lineOfSight.y,
_vecLightDirectionTransformed[index].z + lineOfSight.z,
_vecLightDirectionTransformed[index].w + lineOfSight.w
};
//normalize the half angle vector
//can't believe the hardware really does this... but yet it seems...
s32 halfLength = ((s32)(sqrt((double)vec3dot_fixed32(_cacheHalfVector[index].vec, _cacheHalfVector[index].vec))))<<6;
s32 halfLength = ( (s32)(sqrt((double)vec3dot_fixed32(half.vec, half.vec))) ) << 6;
if (halfLength != 0)
{
@ -1839,12 +1841,18 @@ static void gfx3d_glLightDirection_cache(const size_t index)
halfLength >>= 6;
for (size_t i = 0; i < 4; i++)
{
s32 temp = _cacheHalfVector[index].vec[i];
s32 temp = half.vec[i];
temp <<= 6;
temp /= halfLength;
_cacheHalfVector[index].vec[i] = temp;
half.vec[i] = temp;
}
}
_vecLightDirectionHalfNegative[index].x = -half.x;
_vecLightDirectionHalfNegative[index].y = -half.y;
_vecLightDirectionHalfNegative[index].z = -half.z;
_vecLightDirectionHalfNegative[index].w = -half.w;
_doesLightHalfVectorNeedUpdate[index] = false;
}
@ -2045,16 +2053,14 @@ static void gfx3d_glNormal(const u32 param)
//This formula is the one used by the DS
//Reference : http://nocash.emubase.de/gbatek.htm#ds3dpolygonlightparameters
const s32 fixed_diffuse = std::max( 0, -vec3dot_fixed32(_cacheLightDirection[i].vec, normal.vec) );
const s32 fixed_diffuse = std::max( 0, -vec3dot_fixed32(_vecLightDirectionTransformed[i].vec, normal.vec) );
//todo - this could be cached in this form
const Vector32x4 fixedTempNegativeHalf = {
-_cacheHalfVector[i].x,
-_cacheHalfVector[i].y,
-_cacheHalfVector[i].z,
-_cacheHalfVector[i].w
};
const s32 dot = vec3dot_fixed32(fixedTempNegativeHalf.vec, normal.vec);
if (_doesLightHalfVectorNeedUpdate[i])
{
gfx3d_UpdateLightDirectionHalfAngleVector(i);
}
const s32 dot = vec3dot_fixed32(_vecLightDirectionHalfNegative[i].vec, normal.vec);
s32 fixedshininess = 0;
if (dot > 0) //prevent shininess on opposite side
@ -2098,10 +2104,10 @@ static void gfx3d_glNormal(const u32 param)
_gEngine.SetVertexColor(newVtxColor);
GFX_DELAY(9);
GFX_DELAY_M2((lightMask >> 0) & 0x01);
GFX_DELAY_M2((lightMask >> 1) & 0x01);
GFX_DELAY_M2((lightMask >> 2) & 0x01);
GFX_DELAY_M2((lightMask >> 3) & 0x01);
GFX_DELAY_M2(_regPolyAttrApplied.Light0);
GFX_DELAY_M2(_regPolyAttrApplied.Light1);
GFX_DELAY_M2(_regPolyAttrApplied.Light2);
GFX_DELAY_M2(_regPolyAttrApplied.Light3);
}
static void gfx3d_glTexCoord(const u32 param)
@ -2201,10 +2207,18 @@ static void gfx3d_glMaterial1(const u32 param)
// 30-31 Light Number (0..3)
static void gfx3d_glLightDirection(const u32 param)
{
const size_t index = param >> 30;
_regLightDirection[index] = param & 0x3FFFFFFF;
gfx3d_glLightDirection_cache(index);
const size_t index = (param >> 30) & 0x00000003;
const u32 v = param & 0x3FFFFFFF;
_regLightDirection[index] = v;
// Unpack the vector, and then multiply it by the current directional matrix.
_vecLightDirectionTransformed[index].x = ((s32)((v<<22) & 0xFFC00000) / (s32)(1<<22)) * (s32)(1<<3);
_vecLightDirectionTransformed[index].y = ((s32)((v<<12) & 0xFFC00000) / (s32)(1<<22)) * (s32)(1<<3);
_vecLightDirectionTransformed[index].z = ((s32)((v<< 2) & 0xFFC00000) / (s32)(1<<22)) * (s32)(1<<3);
_vecLightDirectionTransformed[index].w = 0;
MatrixMultVec3x3(_mtxCurrent[MATRIXMODE_POSITION_VECTOR], _vecLightDirectionTransformed[index].vec);
_doesLightHalfVectorNeedUpdate[index] = true;
GFX_DELAY(6);
}
@ -3602,18 +3616,24 @@ void gfx3d_savestate(EMUFILE &os)
// evidently these need to be saved because we don't cache the matrix that would need to be used to properly regenerate them
for (size_t i = 0; i < 4; i++)
{
os.write_32LE(_cacheLightDirection[i].x);
os.write_32LE(_cacheLightDirection[i].y);
os.write_32LE(_cacheLightDirection[i].z);
os.write_32LE(_cacheLightDirection[i].w);
os.write_32LE(_vecLightDirectionTransformed[i].x);
os.write_32LE(_vecLightDirectionTransformed[i].y);
os.write_32LE(_vecLightDirectionTransformed[i].z);
os.write_32LE(_vecLightDirectionTransformed[i].w);
}
for (size_t i = 0; i < 4; i++)
{
os.write_32LE(_cacheHalfVector[i].x);
os.write_32LE(_cacheHalfVector[i].y);
os.write_32LE(_cacheHalfVector[i].z);
os.write_32LE(_cacheHalfVector[i].w);
if (_doesLightHalfVectorNeedUpdate[i])
{
gfx3d_UpdateLightDirectionHalfAngleVector(i);
}
// Historically, these values were saved with the opposite sign.
os.write_32LE(-_vecLightDirectionHalfNegative[i].x);
os.write_32LE(-_vecLightDirectionHalfNegative[i].y);
os.write_32LE(-_vecLightDirectionHalfNegative[i].z);
os.write_32LE(-_vecLightDirectionHalfNegative[i].w);
}
}
@ -3628,11 +3648,6 @@ bool gfx3d_loadstate(EMUFILE &is, int size)
GPU->ForceRender3DFinishAndFlush(false);
}
gfx3d_glLightDirection_cache(0);
gfx3d_glLightDirection_cache(1);
gfx3d_glLightDirection_cache(2);
gfx3d_glLightDirection_cache(3);
gfx3d_parseCurrentDISP3DCNT();
if (version >= 1)
@ -3716,18 +3731,25 @@ bool gfx3d_loadstate(EMUFILE &is, int size)
{
for (size_t i = 0; i < 4; i++)
{
is.read_32LE(_cacheLightDirection[i].x);
is.read_32LE(_cacheLightDirection[i].y);
is.read_32LE(_cacheLightDirection[i].z);
is.read_32LE(_cacheLightDirection[i].w);
is.read_32LE(_vecLightDirectionTransformed[i].x);
is.read_32LE(_vecLightDirectionTransformed[i].y);
is.read_32LE(_vecLightDirectionTransformed[i].z);
is.read_32LE(_vecLightDirectionTransformed[i].w);
}
for (size_t i = 0; i < 4; i++)
{
is.read_32LE(_cacheHalfVector[i].x);
is.read_32LE(_cacheHalfVector[i].y);
is.read_32LE(_cacheHalfVector[i].z);
is.read_32LE(_cacheHalfVector[i].w);
is.read_32LE(_vecLightDirectionHalfNegative[i].x);
is.read_32LE(_vecLightDirectionHalfNegative[i].y);
is.read_32LE(_vecLightDirectionHalfNegative[i].z);
is.read_32LE(_vecLightDirectionHalfNegative[i].w);
// Historically, these values were saved with the opposite sign.
_vecLightDirectionHalfNegative[i].x = -_vecLightDirectionHalfNegative[i].x;
_vecLightDirectionHalfNegative[i].y = -_vecLightDirectionHalfNegative[i].y;
_vecLightDirectionHalfNegative[i].z = -_vecLightDirectionHalfNegative[i].z;
_vecLightDirectionHalfNegative[i].w = -_vecLightDirectionHalfNegative[i].w;
_doesLightHalfVectorNeedUpdate[i] = false;
}
}