diff options
author | Fire-Head <Fire-Head@users.noreply.github.com> | 2020-07-29 11:17:53 +0200 |
---|---|---|
committer | Fire-Head <Fire-Head@users.noreply.github.com> | 2020-07-29 11:17:53 +0200 |
commit | 1803dcc873df329282adab46e1d42baa4b6ee45b (patch) | |
tree | d78ac699caa9124338701a5e413b70379204c8a3 /src/render/ShadowCamera.cpp | |
parent | NULL->nil (diff) | |
download | re3-1803dcc873df329282adab46e1d42baa4b6ee45b.tar re3-1803dcc873df329282adab46e1d42baa4b6ee45b.tar.gz re3-1803dcc873df329282adab46e1d42baa4b6ee45b.tar.bz2 re3-1803dcc873df329282adab46e1d42baa4b6ee45b.tar.lz re3-1803dcc873df329282adab46e1d42baa4b6ee45b.tar.xz re3-1803dcc873df329282adab46e1d42baa4b6ee45b.tar.zst re3-1803dcc873df329282adab46e1d42baa4b6ee45b.zip |
Diffstat (limited to '')
-rw-r--r-- | src/render/ShadowCamera.cpp | 551 |
1 files changed, 551 insertions, 0 deletions
diff --git a/src/render/ShadowCamera.cpp b/src/render/ShadowCamera.cpp new file mode 100644 index 00000000..82d10a88 --- /dev/null +++ b/src/render/ShadowCamera.cpp @@ -0,0 +1,551 @@ +#include "common.h" +#include "rwcore.h" +#include "ShadowCamera.h" +#include "RwHelper.h" + +#define TEXELOFFSET 0.5f + +RpAtomic *ShadowRenderCallBack(RpAtomic *atomic, void *data) +{ + RpAtomicCallBackRender savedCB = RpAtomicGetRenderCallBack(atomic); + RpAtomicSetRenderCallBack(atomic, AtomicDefaultRenderCallBack); + RpAtomicRender(atomic); + RpAtomicSetRenderCallBack(atomic, savedCB); + return atomic; +} + +CShadowCamera::CShadowCamera() +{ + m_pCamera = NULL; + m_pTexture = NULL; +} + +CShadowCamera::~CShadowCamera() +{ + Destroy(); +} + +void +CShadowCamera::Destroy() +{ + if ( m_pCamera ) + { + RwRaster *raster; + RwFrame *frame; + + frame = RwCameraGetFrame(m_pCamera); + + if ( frame ) + { + RwCameraSetFrame(m_pCamera, NULL); + RwFrameDestroy(frame); + } + + raster = RwCameraGetZRaster(m_pCamera); + if ( raster ) + { + RwCameraSetZRaster(m_pCamera, NULL); + RwRasterDestroy(raster); + } + + raster = RwCameraGetRaster(m_pCamera); + if ( raster ) + { + RwCameraSetRaster(m_pCamera, NULL); + RwRasterDestroy(raster); + } + + if ( m_pTexture ) + { + RwTextureSetRaster(m_pTexture, NULL); + RwTextureDestroy(m_pTexture); + m_pTexture = NULL; + } + + RwCameraDestroy(m_pCamera); + m_pCamera = NULL; + } + return; +} + +RwCamera * +CShadowCamera::Create(int32 rasterSize) +{ + int32 size = 1 << rasterSize; + + m_pCamera = RwCameraCreate(); + ASSERT(m_pCamera != NULL); + + if ( m_pCamera ) + { + RwCameraSetFrame(m_pCamera, RwFrameCreate()); + + if( RwCameraGetFrame(m_pCamera) ) + { + RwRaster *zRaster = RwRasterCreate(size, size, 0, rwRASTERTYPEZBUFFER); + ASSERT(zRaster != NULL); + + if ( zRaster ) + { + RwCameraSetZRaster(m_pCamera, zRaster); + + RwRaster *raster = RwRasterCreate(size, size, 0, rwRASTERTYPECAMERATEXTURE); + ASSERT(raster != NULL); + + if ( raster ) + { + RwCameraSetRaster(m_pCamera, raster); + m_pTexture = RwTextureCreate(raster); + ASSERT(m_pTexture != NULL); + + if ( m_pTexture ) + { + RwTextureSetAddressing(m_pTexture, rwTEXTUREADDRESSCLAMP); + RwTextureSetFilterMode(m_pTexture, rwFILTERLINEAR); + RwCameraSetProjection(m_pCamera, rwPARALLEL); + return (m_pCamera); + } + } + } + } + } + + Destroy(); + + return (NULL); +} + +RwCamera * +CShadowCamera::SetFrustum(float objectRadius) +{ + ASSERT(m_pCamera != NULL); + + RwV2d vw; + + RwCameraSetFarClipPlane (m_pCamera, 2.0f * objectRadius); + RwCameraSetNearClipPlane(m_pCamera, 0.001f * objectRadius); + + vw.x = objectRadius; + vw.y = objectRadius; + RwCameraSetViewWindow(m_pCamera, &vw); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::SetLight(RpLight *light) +{ + ASSERT(light != NULL); + ASSERT(m_pCamera != NULL); + + RwFrame *camFrame = RwCameraGetFrame(m_pCamera); + RwMatrix *camMatrix = RwFrameGetMatrix(camFrame); + RwFrame *lightFrame = RpLightGetFrame(light); + RwMatrix *lightMatrix = RwFrameGetMatrix(lightFrame); + + *RwMatrixGetRight(camMatrix) = *RwMatrixGetRight(lightMatrix); + *RwMatrixGetUp(camMatrix) = *RwMatrixGetUp(lightMatrix); + *RwMatrixGetAt(camMatrix) = *RwMatrixGetAt(lightMatrix); + + //RwMatrixCopy(RwFrameGetMatrix(camFrame), RwFrameGetMatrix(lightFrame)); + + RwMatrixUpdate(RwFrameGetMatrix(camFrame)); + RwFrameUpdateObjects(camFrame); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::SetCenter(RwV3d *center) +{ + ASSERT(center != NULL); + ASSERT(m_pCamera != NULL); + + RwFrame *camFrame = RwCameraGetFrame(m_pCamera); + RwMatrix *camMatrix = RwFrameGetMatrix(camFrame); + + *RwMatrixGetPos(camMatrix) = *center; + + RwV3dIncrementScaled(RwMatrixGetPos(camMatrix), RwMatrixGetAt(camMatrix), -0.5f * RwCameraGetFarClipPlane(m_pCamera)); + + RwMatrixUpdate(camMatrix); + RwFrameUpdateObjects(camFrame); + RwFrameOrthoNormalize(camFrame); + + return m_pCamera; +} + +RwCamera * +CShadowCamera::Update(RpClump *clump) +{ + ASSERT(clump != NULL); + ASSERT(m_pCamera != NULL); + + RwUInt32 flags; + RpGeometry *geometry; + + RwRGBA bgColor = { 255, 255, 255, 0 }; + + RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + geometry = GetFirstAtomic(clump)->geometry; + ASSERT(geometry != NULL); + + flags = RpGeometryGetFlags(geometry); + + RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT + |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR)); + + RpClumpForAllAtomics(clump, ShadowRenderCallBack, NULL); + + RpGeometrySetFlags(geometry, flags); + + InvertRaster(); + RwCameraEndUpdate(m_pCamera); + } + + return m_pCamera; +} + +RwCamera * +CShadowCamera::Update(RpAtomic *atomic) +{ + ASSERT(atomic != NULL); + ASSERT(m_pCamera != NULL); + + RwUInt32 flags; + RpGeometry *geometry; + + RwRGBA bgColor = { 255, 255, 255, 0 }; + + RwCameraClear(m_pCamera, &bgColor, rwCAMERACLEARZ | rwCAMERACLEARIMAGE); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + geometry = RpAtomicGetGeometry(atomic); + ASSERT(geometry != NULL); + flags = RpGeometryGetFlags(geometry); + + RpGeometrySetFlags(geometry, flags & ~(rpGEOMETRYPRELIT|rpGEOMETRYLIGHT + |rpGEOMETRYTEXTURED|rpGEOMETRYTEXTURED2|rpGEOMETRYMODULATEMATERIALCOLOR|rpGEOMETRYNORMALS)); + + ShadowRenderCallBack(atomic, NULL); + + RpGeometrySetFlags(geometry, flags); + + InvertRaster(); + RwCameraEndUpdate(m_pCamera); + } + + return m_pCamera; +} + +void +CShadowCamera::InvertRaster() +{ + ASSERT(m_pCamera != NULL); + + RwIm2DVertex vx[4]; + float crw, crh; + RwRaster *raster; + float recipZ; + + raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != NULL); + + crw = (float)RwRasterGetWidth(raster); + crh = (float)RwRasterGetHeight(raster); + + recipZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], 0.0f); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipZ); + RwIm2DVertexSetIntRGBA (&vx[0], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[1], 0.0f); + RwIm2DVertexSetScreenY (&vx[1], crh); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipZ); + RwIm2DVertexSetIntRGBA (&vx[1], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[2], crw); + RwIm2DVertexSetScreenY (&vx[2], 0.0f); + RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[2], recipZ); + RwIm2DVertexSetIntRGBA (&vx[2], 255, 255, 255, 255); + + RwIm2DVertexSetScreenX (&vx[3], crw); + RwIm2DVertexSetScreenY (&vx[3], crh); + RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[3], recipZ); + RwIm2DVertexSetIntRGBA (&vx[3], 255, 255, 255, 255); + + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)NULL); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + + RwIm2DRenderPrimitive(rwPRIMTYPETRISTRIP, vx, 4); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); +} + +RwRaster * +CShadowCamera::MakeGradientRaster() +{ + ASSERT(m_pCamera != NULL); + + RwIm2DVertex vx[2]; + + if ( !m_pCamera ) + return NULL; + + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != NULL); + + float width = (float)RwRasterGetWidth(raster); + float height = (float)RwRasterGetHeight(raster); + + if ( height < 1 ) + return NULL; + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)rwFILTERNAFILTERMODE); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDINVDESTCOLOR); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEFLAT); + + float color = 255.0f; + float step = (-191.0f / height); + + for ( int32 i = 0; i < height; i++ ) + { + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], i); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ); + RwIm2DVertexSetIntRGBA (&vx[0], (uint32)color, (uint32)color, (uint32)color, (uint32)color); + + RwIm2DVertexSetScreenX (&vx[1], width - 1); + RwIm2DVertexSetScreenY (&vx[1], i); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ); + RwIm2DVertexSetIntRGBA (&vx[1], (uint32)color, (uint32)color, (uint32)color, (uint32)color); + + RwIm2DRenderLine(vx, 2, 0, 1); + + color += step; + } + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATESHADEMODE, (void *)rwSHADEMODEGOURAUD); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +} + +RwRaster * +CShadowCamera::RasterResample(RwRaster *dstRaster) +{ + ASSERT(dstRaster != NULL); + ASSERT(m_pCamera != NULL); + + if ( !m_pCamera ) + return NULL; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != NULL); + + float size = (float) RwRasterGetWidth(raster); + float uvOffset = TEXELOFFSET / size; + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster); + + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, uvOffset); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +} + +RwRaster * +CShadowCamera::RasterBlur(RwRaster *dstRaster, int32 numPasses) +{ + ASSERT(dstRaster != NULL); + ASSERT(m_pCamera != NULL); + + if ( !m_pCamera ) + return NULL; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != NULL); + + float size = (float) RwRasterGetWidth(dstRaster); + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + for (int i = 0; i < numPasses; i++ ) + { + RwCameraSetRaster(m_pCamera, raster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + if ( i == 0 ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDONE); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + } + + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)dstRaster); + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 1.0f / size); + RwCameraEndUpdate(m_pCamera); + } + + RwCameraSetRaster(m_pCamera, dstRaster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster); + Im2DRenderQuad(0.0f, 0.0f, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0); + + if ( i == numPasses - 1 ) + { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + } + + RwCameraEndUpdate(m_pCamera); + } + } + + RwCameraSetRaster(m_pCamera, raster); + + return dstRaster; +} + +RwRaster * +CShadowCamera::RasterGradient(RwRaster *dstRaster) +{ + ASSERT(dstRaster != NULL); + ASSERT(m_pCamera != NULL); + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != NULL); + + float size = (float)RwRasterGetWidth(dstRaster); + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwCameraSetRaster(m_pCamera, dstRaster); + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDSRCCOLOR); + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void *)rwFILTERLINEAR); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)raster); + + Im2DRenderQuad(0, 0, size, size, RwIm2DGetNearScreenZ(), recipCamZ, 0); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void *)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void *)rwBLENDINVSRCALPHA); + + RwCameraEndUpdate(m_pCamera); + } + + RwCameraSetRaster(m_pCamera, raster); + + return dstRaster; +} + +RwRaster *CShadowCamera::DrawOutlineBorder(RwRGBA const& color) +{ + ASSERT(m_pCamera != NULL); + + RwIm2DVertex vx[4]; + RwImVertexIndex ix[5]; + + RwRaster *raster = RwCameraGetRaster(m_pCamera); + ASSERT(raster != NULL); + + float size = (float)RwRasterGetWidth(raster) - 1.0f; + float recipCamZ = 1.0f / RwCameraGetNearClipPlane(m_pCamera); + + RwIm2DVertexSetScreenX (&vx[0], 0.0f); + RwIm2DVertexSetScreenY (&vx[0], 0.0f); + RwIm2DVertexSetScreenZ (&vx[0], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[0], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[0], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[1], size); + RwIm2DVertexSetScreenY (&vx[1], 0.0f); + RwIm2DVertexSetScreenZ (&vx[1], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[1], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[1], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[2], size); + RwIm2DVertexSetScreenY (&vx[2], size); + RwIm2DVertexSetScreenZ (&vx[2], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[2], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[2], recipCamZ); + + RwIm2DVertexSetScreenX (&vx[3], 0.0f); + RwIm2DVertexSetScreenY (&vx[3], size); + RwIm2DVertexSetScreenZ (&vx[3], RwIm2DGetNearScreenZ()); + RwIm2DVertexSetIntRGBA (&vx[3], color.red, color.green, color.blue, color.alpha); + RwIm2DVertexSetRecipCameraZ(&vx[3], recipCamZ); + + ix[0] = 0; + ix[4] = 0; + ix[1] = 1; + ix[2] = 2; + ix[3] = 3; + + if ( RwCameraBeginUpdate(m_pCamera) ) + { + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)FALSE); + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, (void *)NULL); + + RwIm2DRenderIndexedPrimitive(rwPRIMTYPEPOLYLINE, vx, 4, ix, 5); + + RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void *)TRUE); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void *)TRUE); + + RwCameraEndUpdate(m_pCamera); + } + + return raster; +}
\ No newline at end of file |