1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-06-25 22:09:35 +00:00

Correct lighting for CBFD.

Code refactoring.
This commit is contained in:
Sergey Lipskiy 2019-01-05 16:30:42 +07:00
parent b036a8296e
commit 31e2c7e11a
4 changed files with 131 additions and 105 deletions

View File

@ -138,6 +138,7 @@ void RSP_ProcessDList()
gSP.status[0] = gSP.status[1] = gSP.status[2] = gSP.status[3] = 0;
gSP.changed |= CHANGED_MATRIX | CHANGED_LIGHT | CHANGED_LOOKAT;
gSP.tri_num = 0;
gSP.cbfd.advancedLighting = false;
gDP.changed &= ~CHANGED_CPU_FB_WRITE;
gDPSetTexturePersp(G_TP_PERSP);

View File

@ -511,26 +511,34 @@ void gSPLightVertexStandard(u32 v, SPVertex * spVtx)
}
template <u32 VNUM>
void gSPLightVertexCBFD(u32 v, SPVertex * spVtx)
void gSPLightVertexCBFD_basic(u32 v, SPVertex * spVtx)
{
for (int j = 0; j < VNUM; ++j) {
SPVertex & vtx = spVtx[v + j];
vtx.HWLight = 0;
if (vtx.flag < 0)
continue;
f32 r = gSP.lights.rgb[gSP.numLights][R];
f32 g = gSP.lights.rgb[gSP.numLights][G];
f32 b = gSP.lights.rgb[gSP.numLights][B];
f32 recip = FIXED2FLOATRECIP16;
const f32 vPos[3] = {
(vtx.x + gSP.cbfd.vertexCoordMod[ 8])*gSP.cbfd.vertexCoordMod[12],
(vtx.y + gSP.cbfd.vertexCoordMod[ 9])*gSP.cbfd.vertexCoordMod[13],
(vtx.z + gSP.cbfd.vertexCoordMod[10])*gSP.cbfd.vertexCoordMod[14]
};
for (u32 l = 0; l < gSP.numLights; ++l) {
const f32 vx = (vtx.x + gSP.vertexCoordMod[8])*gSP.vertexCoordMod[12] - gSP.lights.pos_xyzw[l][X];
const f32 vy = (vtx.y + gSP.vertexCoordMod[9])*gSP.vertexCoordMod[13] - gSP.lights.pos_xyzw[l][Y];
const f32 vz = (vtx.z + gSP.vertexCoordMod[10])*gSP.vertexCoordMod[14] - gSP.lights.pos_xyzw[l][Z];
const f32 vw = (vtx.w + gSP.vertexCoordMod[11])*gSP.vertexCoordMod[15] - gSP.lights.pos_xyzw[l][W];
const f32 len = (vx*vx + vy*vy + vz*vz + vw*vw) * recip;
f32 intensity = gSP.lights.ca[l] / len;
if (intensity > 1.0f) intensity = 1.0f;
r += gSP.lights.rgb[l][R] * intensity;
g += gSP.lights.rgb[l][G] * intensity;
b += gSP.lights.rgb[l][B] * intensity;
for (int l = gSP.numLights - 2; l >= 0; --l) {
const f32 vx = vPos[X] - gSP.lights.pos_xyzw[l][X];
const f32 vy = vPos[Y] - gSP.lights.pos_xyzw[l][Y];
const f32 vz = vPos[Z] - gSP.lights.pos_xyzw[l][Z];
const f32 len = 2.0f * (vx*vx + vy*vy + vz*vz) * FIXED2FLOATRECIP16;
f32 intensity = std::min(1.0f, gSP.lights.ca[l] / len);
if (intensity > 0.0f) {
r += gSP.lights.rgb[l][R] * intensity;
g += gSP.lights.rgb[l][G] * intensity;
b += gSP.lights.rgb[l][B] * intensity;
}
}
r = min(1.0f, r);
@ -540,16 +548,69 @@ void gSPLightVertexCBFD(u32 v, SPVertex * spVtx)
vtx.r *= r;
vtx.g *= g;
vtx.b *= b;
}
}
template <u32 VNUM>
void gSPLightVertexCBFD_advanced(u32 v, SPVertex * spVtx)
{
for (int j = 0; j < VNUM; ++j) {
SPVertex & vtx = spVtx[v + j];
vtx.HWLight = 0;
if (vtx.flag < 0)
continue;
const f32 vPos[3] = {
(vtx.x + gSP.cbfd.vertexCoordMod[ 8])*gSP.cbfd.vertexCoordMod[12],
(vtx.y + gSP.cbfd.vertexCoordMod[ 9])*gSP.cbfd.vertexCoordMod[13],
(vtx.z + gSP.cbfd.vertexCoordMod[10])*gSP.cbfd.vertexCoordMod[14]
};
int l = gSP.numLights;
f32 r = gSP.lights.rgb[l][R];
f32 g = gSP.lights.rgb[l][G];
f32 b = gSP.lights.rgb[l][B];
--l;
f32 intensity = std::min(1.0f, DotProduct(&vtx.nx, gSP.lights.i_xyz[l]));
if (intensity > 0.0f) {
r += gSP.lights.rgb[l][R] * intensity;
g += gSP.lights.rgb[l][G] * intensity;
b += gSP.lights.rgb[l][B] * intensity;
}
while (--l >= 0) {
const f32 vx = vPos[X] - gSP.lights.pos_xyzw[l][X];
const f32 vy = vPos[Y] - gSP.lights.pos_xyzw[l][Y];
const f32 vz = vPos[Z] - gSP.lights.pos_xyzw[l][Z];
const f32 len = 2.0f * (vx*vx + vy*vy + vz*vz) * FIXED2FLOATRECIP16;
intensity = std::min(1.0f, gSP.lights.ca[l] / len);
if ((gSP.geometryMode & G_POINT_LIGHTING) != 0)
intensity *= std::min(1.0f, DotProduct(&vtx.nx, gSP.lights.i_xyz[l]));;
if (intensity > 0.0f) {
r += gSP.lights.rgb[l][R] * intensity;
g += gSP.lights.rgb[l][G] * intensity;
b += gSP.lights.rgb[l][B] * intensity;
}
}
r = min(1.0f, r);
g = min(1.0f, g);
b = min(1.0f, b);
vtx.r *= r;
vtx.g *= g;
vtx.b *= b;
}
}
template <u32 VNUM>
void gSPLightVertex(u32 _v, SPVertex * _spVtx)
{
if (g_ConkerUcode)
gSPLightVertexCBFD<VNUM>(_v, _spVtx);
else
if (g_ConkerUcode) {
if (gSP.cbfd.advancedLighting)
gSPLightVertexCBFD_advanced<VNUM>(_v, _spVtx);
else
gSPLightVertexCBFD_basic<VNUM>(_v, _spVtx);
} else
gSPLightVertexStandard<VNUM>(_v, _spVtx);
}
@ -617,59 +678,15 @@ void gSPPointLightVertexZeldaMM(u32 v, float _vecPos[VNUM][4], SPVertex * spVtx)
}
}
template <u32 VNUM>
void gSPPointLightVertexCBFD(u32 v, SPVertex * spVtx)
{
f32 intensity = 0.0f;
for (int j = 0; j < VNUM; ++j) {
SPVertex & vtx = spVtx[v + j];
f32 r = gSP.lights.rgb[gSP.numLights][R];
f32 g = gSP.lights.rgb[gSP.numLights][G];
f32 b = gSP.lights.rgb[gSP.numLights][B];
for (u32 l = 0; l < gSP.numLights - 1; ++l) {
intensity = DotProduct(&vtx.nx, gSP.lights.xyz[l]);
if ((gSP.lights.rgb[l][R] == 0.0f && gSP.lights.rgb[l][G] == 0.0f && gSP.lights.rgb[l][B] == 0.0f) || intensity < 0.0f)
continue;
if (gSP.lights.ca[l] > 0.0f) {
const f32 vx = (vtx.x + gSP.vertexCoordMod[8])*gSP.vertexCoordMod[12] - gSP.lights.pos_xyzw[l][X];
const f32 vy = (vtx.y + gSP.vertexCoordMod[9])*gSP.vertexCoordMod[13] - gSP.lights.pos_xyzw[l][Y];
const f32 vz = (vtx.z + gSP.vertexCoordMod[10])*gSP.vertexCoordMod[14] - gSP.lights.pos_xyzw[l][Z];
const f32 vw = (vtx.w + gSP.vertexCoordMod[11])*gSP.vertexCoordMod[15] - gSP.lights.pos_xyzw[l][W];
const f32 len = _FIXED2FLOAT((vx*vx + vy*vy + vz*vz + vw*vw),16);
float p_i = gSP.lights.ca[l] / len;
if (p_i > 1.0f) p_i = 1.0f;
intensity *= p_i;
}
r += gSP.lights.rgb[l][R] * intensity;
g += gSP.lights.rgb[l][G] * intensity;
b += gSP.lights.rgb[l][B] * intensity;
}
intensity = DotProduct(&vtx.nx, gSP.lights.i_xyz[gSP.numLights - 1]);
if ((gSP.lights.i_xyz[gSP.numLights - 1][R] != 0.0 || gSP.lights.i_xyz[gSP.numLights - 1][G] != 0.0 || gSP.lights.i_xyz[gSP.numLights - 1][B] != 0.0) && intensity > 0) {
r += gSP.lights.rgb[gSP.numLights - 1][R] * intensity;
g += gSP.lights.rgb[gSP.numLights - 1][G] * intensity;
b += gSP.lights.rgb[gSP.numLights - 1][B] * intensity;
}
r = min(1.0f, r);
g = min(1.0f, g);
b = min(1.0f, b);
vtx.r *= r;
vtx.g *= g;
vtx.b *= b;
vtx.HWLight = 0;
}
}
template <u32 VNUM>
void gSPPointLightVertex(u32 _v, float _vecPos[VNUM][4], SPVertex * _spVtx)
{
if (g_ConkerUcode)
gSPPointLightVertexCBFD<VNUM>(_v, _spVtx);
else
if (g_ConkerUcode) {
if (gSP.cbfd.advancedLighting)
gSPLightVertexCBFD_advanced<VNUM>(_v, _spVtx);
else
gSPLightVertexCBFD_basic<VNUM>(_v, _spVtx);
} else
gSPPointLightVertexZeldaMM<VNUM>(_v, _vecPos, _spVtx);
}
@ -1070,10 +1087,11 @@ u32 gSPLoadCBFDVertexData(const Vertex *orgVtx, SPVertex * spVtx, u32 v0, u32 vi
vtx.z = orgVtx->z;
vtx.s = _FIXED2FLOAT( orgVtx->s, 5 );
vtx.t = _FIXED2FLOAT( orgVtx->t, 5 );
vtx.flag = orgVtx->flag;
if (gSP.geometryMode & G_LIGHTING) {
const u32 normaleAddrOffset = ((vi+j)<<1);
vtx.nx = _FIXED2FLOATCOLOR(((s8*)RDRAM)[(gSP.vertexNormalBase + normaleAddrOffset + 0) ^ 3], 7);
vtx.ny = _FIXED2FLOATCOLOR(((s8*)RDRAM)[(gSP.vertexNormalBase + normaleAddrOffset + 1) ^ 3], 7);
vtx.nx = _FIXED2FLOATCOLOR(((s8*)RDRAM)[(gSP.cbfd.vertexNormalBase + normaleAddrOffset + 0) ^ 3], 7);
vtx.ny = _FIXED2FLOATCOLOR(((s8*)RDRAM)[(gSP.cbfd.vertexNormalBase + normaleAddrOffset + 1) ^ 3], 7);
vtx.nz = _FIXED2FLOATCOLOR((s8)(orgVtx->flag & 0xFF), 7);
}
vtx.r = _FIXED2FLOATCOLOR(orgVtx->color.r, 8);
@ -1433,13 +1451,6 @@ void gSPSetVertexColorBase( u32 base )
DebugMsg(DEBUG_NORMAL, "gSPSetVertexColorBase( 0x%08X );\n", base );
}
void gSPSetVertexNormaleBase( u32 base )
{
gSP.vertexNormalBase = RSP_SegmentToPhysical( base );
DebugMsg(DEBUG_NORMAL, "gSPSetVertexNormaleBase( 0x%08X );\n", base );
}
void gSPDMATriangles( u32 tris, u32 n ){
const u32 address = RSP_SegmentToPhysical( tris );
@ -1713,28 +1724,6 @@ void gSPPerspNormalize( u16 scale )
DebugMsg(DEBUG_NORMAL| DEBUG_IGNORED, "gSPPerspNormalize( %i );\n", scale);
}
void gSPCoordMod(u32 _w0, u32 _w1)
{
DebugMsg(DEBUG_NORMAL, "gSPCoordMod( %u, %u );\n", _w0, _w1);
if ((_w0 & 8) != 0)
return;
u32 idx = _SHIFTR(_w0, 1, 2);
u32 pos = _w0&0x30;
if (pos == 0) {
gSP.vertexCoordMod[0+idx] = (f32)(s16)_SHIFTR(_w1, 16, 16);
gSP.vertexCoordMod[1+idx] = (f32)(s16)_SHIFTR(_w1, 0, 16);
} else if (pos == 0x10) {
assert(idx < 3);
gSP.vertexCoordMod[4+idx] = _FIXED2FLOAT(_SHIFTR(_w1, 16, 16),16);
gSP.vertexCoordMod[5+idx] = _FIXED2FLOAT(_SHIFTR(_w1, 0, 16),16);
gSP.vertexCoordMod[12+idx] = gSP.vertexCoordMod[0+idx] + gSP.vertexCoordMod[4+idx];
gSP.vertexCoordMod[13+idx] = gSP.vertexCoordMod[1+idx] + gSP.vertexCoordMod[5+idx];
} else if (pos == 0x20) {
gSP.vertexCoordMod[8+idx] = (f32)(s16)_SHIFTR(_w1, 16, 16);
gSP.vertexCoordMod[9+idx] = (f32)(s16)_SHIFTR(_w1, 0, 16);
}
}
void gSPTexture( f32 sc, f32 tc, u32 level, u32 tile, u32 on )
{
gSP.texture.on = on;

View File

@ -134,9 +134,12 @@ struct gSPInfo
u32 clipRatio;
// CBFD
u32 vertexNormalBase;
f32 vertexCoordMod[16];
struct
{
u32 vertexNormalBase;
f32 vertexCoordMod[16];
bool advancedLighting;
} cbfd;
u32 textureCoordScaleOrg;
u32 textureCoordScale[2];
@ -194,8 +197,6 @@ void gSPSetStatus(u32 sid, u32 val);
void gSPSetDMAOffsets( u32 mtxoffset, u32 vtxoffset );
void gSPSetDMATexOffset(u32 _addr);
void gSPSetVertexColorBase( u32 base );
void gSPSetVertexNormaleBase( u32 base );
void gSPCoordMod(u32 _w0, u32 _w1);
void gSPCombineMatrices(u32 _mode);
void gSPTriangle(s32 v0, s32 v1, s32 v2);

View File

@ -11,6 +11,7 @@
#include "gDP.h"
#include "GBI.h"
static
void F3DEX2CBFD_Vtx( u32 w0, u32 w1 )
{
u32 n = _SHIFTR( w0, 12, 8 );
@ -18,6 +19,31 @@ void F3DEX2CBFD_Vtx( u32 w0, u32 w1 )
gSPCBFDVertex( w1, n, _SHIFTR( w0, 1, 7 ) - n );
}
static
void F3DEX2CBFD_CoordMod(u32 _w0, u32 _w1)
{
DebugMsg(DEBUG_NORMAL, "gSPCoordMod( %u, %u );\n", _w0, _w1);
if ((_w0 & 8) != 0)
return;
u32 idx = _SHIFTR(_w0, 1, 2);
u32 pos = _w0 & 0x30;
if (pos == 0) {
gSP.cbfd.vertexCoordMod[0 + idx] = (f32)(s16)_SHIFTR(_w1, 16, 16);
gSP.cbfd.vertexCoordMod[1 + idx] = (f32)(s16)_SHIFTR(_w1, 0, 16);
}
else if (pos == 0x10) {
gSP.cbfd.vertexCoordMod[4 + idx] = _FIXED2FLOAT(_SHIFTR(_w1, 16, 16), 16);
gSP.cbfd.vertexCoordMod[5 + idx] = _FIXED2FLOAT(_SHIFTR(_w1, 0, 16), 16);
gSP.cbfd.vertexCoordMod[12 + idx] = gSP.cbfd.vertexCoordMod[0 + idx] + gSP.cbfd.vertexCoordMod[4 + idx];
gSP.cbfd.vertexCoordMod[13 + idx] = gSP.cbfd.vertexCoordMod[1 + idx] + gSP.cbfd.vertexCoordMod[5 + idx];
}
else if (pos == 0x20) {
gSP.cbfd.vertexCoordMod[8 + idx] = (f32)(s16)_SHIFTR(_w1, 16, 16);
gSP.cbfd.vertexCoordMod[9 + idx] = (f32)(s16)_SHIFTR(_w1, 0, 16);
}
}
static
void F3DEX2CBFD_MoveWord( u32 w0, u32 w1 )
{
switch (_SHIFTR( w0, 16, 8 ))
@ -38,11 +64,12 @@ void F3DEX2CBFD_MoveWord( u32 w0, u32 w1 )
gSPPerspNormalize( w1 );
break;
case G_MW_COORD_MOD:
gSPCoordMod( w0, w1 );
F3DEX2CBFD_CoordMod( w0, w1 );
break;
}
}
static
void F3DEX2CBFD_MoveMem( u32 w0, u32 w1 )
{
switch (_SHIFTR( w0, 0, 8 ))
@ -61,11 +88,13 @@ void F3DEX2CBFD_MoveMem( u32 w0, u32 w1 )
}
break;
case G_MV_NORMALES:
gSPSetVertexNormaleBase(w1);
gSP.cbfd.vertexNormalBase = RSP_SegmentToPhysical(w1);
DebugMsg(DEBUG_NORMAL, "gSPSetVertexNormaleBase( 0x%08X );\n", w1);
break;
}
}
static
void F3DEX2CBFD_Tri4( u32 w0, u32 w1 )
{
gSP4Triangles( _SHIFTR( w0, 23, 5 ), _SHIFTR( w0, 18, 5 ), (_SHIFTR( w0, 15, 3 )<<2)|_SHIFTR( w1, 30, 2 ),
@ -74,6 +103,12 @@ void F3DEX2CBFD_Tri4( u32 w0, u32 w1 )
_SHIFTR( w1, 10, 5 ), _SHIFTR( w1, 5, 5 ), _SHIFTR( w1, 0, 5 ) );
}
static
void F3DEX2CBFD_SwitchLightingMode(u32, u32)
{
gSP.cbfd.advancedLighting = true;
}
void F3DEX2CBFD_Init()
{
gSPSetupFunctions();
@ -90,7 +125,7 @@ void F3DEX2CBFD_Init()
GBI_SetGBI( G_SPNOOP, F3DEX2_SPNOOP, F3D_SPNoOp );
GBI_SetGBI( G_ENDDL, F3DEX2_ENDDL, F3D_EndDL );
GBI_SetGBI( G_DL, F3DEX2_DL, F3D_DList );
GBI_SetGBI( G_LOAD_UCODE, F3DEX2_LOAD_UCODE, F3DEX_Load_uCode );
GBI_SetGBI( G_LOAD_UCODE, F3DEX2_LOAD_UCODE, F3DEX2CBFD_SwitchLightingMode );
GBI_SetGBI( G_MOVEMEM, F3DEX2_MOVEMEM, F3DEX2CBFD_MoveMem );
GBI_SetGBI( G_MOVEWORD, F3DEX2_MOVEWORD, F3DEX2CBFD_MoveWord );
GBI_SetGBI( G_MTX, F3DEX2_MTX, F3DEX2_Mtx );