Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xShadow progress #376

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
269 changes: 269 additions & 0 deletions src/SB/Core/x/xShadow.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,272 @@
#include "xShadow.h"

#include "rpworld.h"

#include "xMath.h"
#include "iModel.h"
#include "zGlobals.h"

#include <types.h>

RwRGBAReal ShadowLightColor = { 1.0f, 1.0f, 1.0f, 1.0f };

RpLight* ShadowLight;
static F32 SHADOW_BOTH;
RwCamera* ShadowCamera;
RwRaster* ShadowCameraRaster;
static RwRaster* ShadowRenderRaster;
F32 gShadowObjectRadius;
static S32 shadow_ent_count;
static RwRaster* gc_saveraster;
static xShadowMgr* sMgrList;
static S32 sMgrCount;
static S32 sMgrTotal;

void xShadowInit();
static void ShadowCameraDestroy(RwCamera* shadowCamera);
static S32 SetupShadow();
static RwRaster* ShadowRasterCreate(S32 res);
static RwCamera* ShadowCameraCreatePersp(S32 param);
U32 xShadowCameraCreate();
void xShadowRenderWorld(xVec3* a, F32 b, F32 c);
void xShadow_ListAdd(xEnt* ent);
void xShadowManager_Add(xEnt* ent);
static void GCSaveFrameBuffer();
RwCamera* ShadowCameraSetSpherePersp(RwCamera* camera, RwV3d* center, float radius);
int Im2DRenderQuad(float x1, float y1, float x2, float y2, float z, float recipCamZ, float uvOffset);

/* Three more params than in DWARF.
RwCamera* ShadowCameraUpdate(RwCamera* shadowCamera, void* model, void(*renderCB)(void*))
*/
RwCamera* ShadowCameraUpdate(RwCamera* shadowCamera, void* model, void(*renderCB)(void*), RwV3d* center, float radius, int);

void xShadowInit()
{
xShadowCameraCreate();
gc_saveraster = RwRasterCreate(256, 256, 32, 0x504);
shadow_ent_count = 0;
ShadowLight = RpLightCreate(1);
RpLightSetColor(ShadowLight, &ShadowLightColor);
RwFrame* frame = RwFrameCreate();
_rwObjectHasFrameSetFrame(ShadowLight, frame);
}

void xShadowRender(xVec3* a, F32 b, F32 c)
{
xShadowRenderWorld(a, b, c);
}

static S32 SetupShadow()
{
S32 res = 256;

// Continuously halve res until it is less than or
// equal to either display width or height.
// On GCN, this routine normally won't happen,
// as we're already below both dimensions.
for (; (res > 640) || (res > 480); res >>= 1);

ShadowCamera = ShadowCameraCreatePersp(res);
if (ShadowCamera == NULL)
{
return 0;
}
ShadowCameraRaster = ShadowRasterCreate(res);
if (ShadowCameraRaster == NULL)
{
return 0;
}
ShadowCamera->frameBuffer = ShadowCameraRaster;
return 1;
}

void xShadowSetWorld(RpWorld* world)
{
RpWorldAddCamera(world, ShadowCamera);
SHADOW_BOTH = 2.0f;
}

U32 xShadowCameraCreate()
{
U32 setup = SetupShadow();
return ((-setup | setup) >> 0x1f);
}

void xShadowCameraUpdate(void* model, void(*renderCB)(void*), xVec3* center, float radius, int shadowMode)
{
ShadowCameraSetSpherePersp(ShadowCamera, (RwV3d*)center, radius);
ShadowCameraUpdate(ShadowCamera, model, renderCB, (RwV3d*)center, radius, shadowMode);
ShadowRenderRaster = ShadowCameraRaster;
}

static void modelRenderCB(void* param)
{
xModelRender((xModelInstance*)param);
}

S32 xShadowReceiveShadowSetup(xEnt* ent)
{
if
(
(ent->model != NULL) &&
(xEntIsVisible(ent)) &&
(ent->baseFlags & 0x10) &&
(!iModelCull(ent->model->Data, ent->model->Mat))
)
{
return 1;
}
return 0;
}

void xShadow_ListAdd(xEnt* ent)
{
xShadowManager_Add(ent);
}

void ShadowCameraDestroy(RwCamera* shadowCamera)
{
if (shadowCamera == NULL)
{
return;
}

_rwFrameSyncDirty();
RwFrame* parent = (RwFrame*)shadowCamera->object.object.parent;
if (parent != NULL)
{
_rwObjectHasFrameSetFrame(shadowCamera, NULL);
RwFrameDestroy(parent);
}

// Scheduling issue with RwRasterDestroy calls

if (shadowCamera->zBuffer != NULL)
{
RwRasterDestroy(shadowCamera->zBuffer);
shadowCamera->zBuffer = NULL;
}

if (shadowCamera->frameBuffer != NULL)
{
RwRasterDestroy(shadowCamera->frameBuffer);
shadowCamera->frameBuffer = NULL;
}

RwCameraDestroy(shadowCamera);
}

static RwRaster* ShadowRasterCreate(S32 res)
{
return RwRasterCreate(res, res, 0, 5);
}

void GCSaveFrameBuffer()
{
RwGameCubeCameraTextureFlush(gc_saveraster, 0);
}

static void GCRestoreFrameBuffer()
{
RwCamera* cam = *(RwCamera**)RwEngineInstance;
F32 recipCamZ = (1.0f / cam->farPlane);

RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)2);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)1);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)0);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)0);
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)1);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gc_saveraster);

Im2DRenderQuad(0.0f, 0.0f, 256.0f, 256.0f, RwIm2DGetFarScreenZ(), recipCamZ, 0.001953125f);

RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)1);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)1);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)5);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)6);
}

static RwCamera* ShadowCameraCreatePersp(S32 param)
{
RwCamera* cam = RwCameraCreate();
if (cam != NULL)
{
_rwObjectHasFrameSetFrame(cam, RwFrameCreate());

RwV2d viewWin;
viewWin.x = DEG2RAD(10);
viewWin.y = DEG2RAD(10);

RwCameraSetViewWindow(cam, &viewWin);

if (cam->object.object.parent != NULL)
{
RwRaster* raster = RwRasterCreate(param, param, 0, 1);
if (raster != NULL)
{
cam->zBuffer = raster;
return cam;
}
}
}
ShadowCameraDestroy(cam);
return NULL;
}

void xShadowManager_Init(S32 numEnts)
{
sMgrList = (xShadowMgr*)xMemAlloc(gActiveHeap, numEnts << 4, 0);
sMgrTotal = numEnts;
sMgrCount = 0; // Scheduling off
}

void xShadowManager_Reset()
{
sMgrCount = 0;
}

void xShadowManager_Add(xEnt* ent)
{
for (int i = 0; i < sMgrCount; i++)
{
if (sMgrList[i].ent == ent)
{
return;
}
}

if (sMgrCount < sMgrTotal)
{
sMgrList[sMgrCount].ent = ent;
sMgrList[sMgrCount].cache = 0;
sMgrList[sMgrCount].priority = 1000;
sMgrList[sMgrCount].cacheReady = 0;
sMgrCount++;
}
}

void xShadowManager_Remove(xEnt* ent)
{
int a = 0;
for (int i = 6; i < sMgrCount; i++)
{
sMgrList[i].cache = NULL;
a++;
}

a = 0;
int i = 0;
while (a < sMgrCount)
{
if (ent == sMgrList[i].ent)
{
sMgrList[i] = sMgrList[sMgrCount - 1];
sMgrCount--;
}
else
{
i++;
a++;
}
}
}
8 changes: 8 additions & 0 deletions src/SB/Core/x/xShadow.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ struct xShadowCache
xShadowPoly poly[256];
};

struct xShadowMgr
{
xEnt* ent;
xShadowCache* cache;
int priority;
int cacheReady;
};

void xShadow_ListAdd(xEnt* ent);
void xShadowSetWorld(RpWorld* world);
void xShadowSetLight(xVec3* param1, xVec3* param2, F32 param3);
Expand Down