Re3/src/render/MBlur.cpp

323 lines
8.6 KiB
C++
Raw Normal View History

2020-06-30 01:08:50 -04:00
#ifndef LIBRW
2020-06-30 00:43:20 -04:00
#define WITHD3D
2020-06-30 01:08:50 -04:00
#endif
2019-05-30 07:35:13 -04:00
#include "common.h"
2020-06-30 00:43:20 -04:00
#ifndef LIBRW
#include <d3d8caps.h>
#endif
2020-04-17 09:31:11 -04:00
2019-05-30 07:35:13 -04:00
#include "RwHelper.h"
2019-05-31 05:44:43 -04:00
#include "Camera.h"
2019-05-30 07:35:13 -04:00
#include "MBlur.h"
2020-08-13 12:14:24 -04:00
#include "postfx.h"
2019-05-30 07:35:13 -04:00
// Originally taken from RW example 'mblur'
2020-04-17 01:54:14 -04:00
RwRaster *CMBlur::pFrontBuffer;
bool CMBlur::ms_bJustInitialised;
2020-06-27 17:01:51 -04:00
bool CMBlur::ms_bScaledBlur;
2020-04-17 01:54:14 -04:00
bool CMBlur::BlurOn;
2019-05-30 07:35:13 -04:00
static RwIm2DVertex Vertex[4];
static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
2020-06-30 00:43:20 -04:00
#ifndef LIBRW
extern "C" D3DCAPS8 _RwD3D8DeviceCaps;
#endif
2020-06-27 17:01:51 -04:00
RwBool
2019-05-30 07:35:13 -04:00
CMBlur::MotionBlurOpen(RwCamera *cam)
{
2020-08-13 12:14:24 -04:00
#ifdef EXTENDED_COLOURFILTER
CPostFX::Open(cam);
return TRUE;
#else
2020-06-27 17:01:51 -04:00
#ifdef GTA_PS2
RwRect rect = {0, 0, 0, 0};
2020-06-27 17:31:45 -04:00
2020-06-27 17:01:51 -04:00
if (pFrontBuffer)
2020-06-27 17:31:45 -04:00
return TRUE;
2020-06-27 17:01:51 -04:00
BlurOn = true;
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
2020-06-27 17:31:45 -04:00
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
2020-06-27 17:01:51 -04:00
pFrontBuffer = RwRasterCreate(0, 0, 0, rwRASTERDONTALLOCATE|rwRASTERTYPECAMERATEXTURE);
if (!pFrontBuffer)
{
printf("Error creating raster\n");
return FALSE;
}
RwRaster *raster = RwRasterSubRaster(pFrontBuffer, RwCameraGetRaster(cam), &rect);
if (!raster)
{
RwRasterDestroy(pFrontBuffer);
pFrontBuffer = NULL;
printf("Error subrastering\n");
return FALSE;
}
CreateImmediateModeData(cam, &rect);
#else
2019-05-30 07:35:13 -04:00
RwRect rect = { 0, 0, 0, 0 };
if(pFrontBuffer)
MotionBlurClose();
2020-06-27 17:01:51 -04:00
2020-06-29 04:14:00 -04:00
#ifndef LIBRW
2020-06-29 03:36:35 -04:00
extern void _GetVideoMemInfo(LPDWORD total, LPDWORD avaible);
2020-06-29 03:40:06 -04:00
DWORD total, avaible;
2020-06-27 17:01:51 -04:00
_GetVideoMemInfo(&total, &avaible);
debug("Available video memory %d\n", avaible);
2020-06-29 03:36:35 -04:00
#endif
2020-06-27 17:01:51 -04:00
if(BlurOn)
{
2020-06-30 00:43:20 -04:00
uint32 width = Pow(2.0f, int32(log2(RwRasterGetWidth (RwCameraGetRaster(cam))))+1);
uint32 height = Pow(2.0f, int32(log2(RwRasterGetHeight(RwCameraGetRaster(cam))))+1);
uint32 depth = RwRasterGetDepth(RwCameraGetRaster(cam));
2020-06-27 17:01:51 -04:00
#ifndef LIBRW
extern DWORD _dwMemTotalVideo;
if ( _RwD3D8DeviceCaps.MaxTextureWidth >= width && _RwD3D8DeviceCaps.MaxTextureHeight >= height )
{
total = _dwMemTotalVideo - 3 *
( RwRasterGetDepth(RwCameraGetRaster(cam))
* RwRasterGetHeight(RwCameraGetRaster(cam))
* RwRasterGetWidth(RwCameraGetRaster(cam)) / 8 );
BlurOn = total >= height*width*(depth/8) + (12*1024*1024) /*12 MB*/;
}
else
2019-05-30 07:35:13 -04:00
BlurOn = false;
2020-06-27 17:01:51 -04:00
#endif
if ( BlurOn )
{
ms_bScaledBlur = false;
rect.w = width;
rect.h = height;
pFrontBuffer = RwRasterCreate(rect.w, rect.h, depth, rwRASTERTYPECAMERATEXTURE);
if ( !pFrontBuffer )
{
debug("MBlurOpen can't create raster.");
BlurOn = false;
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
}
else
ms_bJustInitialised = true;
}
else
{
2019-05-30 07:35:13 -04:00
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
}
2020-06-27 17:01:51 -04:00
2020-06-29 04:14:00 -04:00
#ifndef LIBRW
2020-06-27 17:01:51 -04:00
_GetVideoMemInfo(&total, &avaible);
debug("Available video memory %d\n", avaible);
2020-06-29 03:36:35 -04:00
#endif
2020-06-29 04:14:00 -04:00
CreateImmediateModeData(cam, &rect);
2020-06-27 17:01:51 -04:00
}
else
{
2019-05-30 07:35:13 -04:00
rect.w = RwRasterGetWidth(RwCameraGetRaster(cam));
rect.h = RwRasterGetHeight(RwCameraGetRaster(cam));
CreateImmediateModeData(cam, &rect);
}
2020-06-27 17:01:51 -04:00
return TRUE;
#endif
2020-08-13 12:14:24 -04:00
#endif
2019-05-30 07:35:13 -04:00
}
2020-06-27 17:01:51 -04:00
RwBool
2019-05-30 07:35:13 -04:00
CMBlur::MotionBlurClose(void)
{
2020-08-13 12:14:24 -04:00
#ifdef EXTENDED_COLOURFILTER
CPostFX::Close();
#else
2019-05-30 07:35:13 -04:00
if(pFrontBuffer){
RwRasterDestroy(pFrontBuffer);
pFrontBuffer = nil;
2020-06-27 17:01:51 -04:00
return TRUE;
2019-05-30 07:35:13 -04:00
}
2020-08-13 12:14:24 -04:00
#endif
2020-06-27 17:01:51 -04:00
return FALSE;
2019-05-30 07:35:13 -04:00
}
void
CMBlur::CreateImmediateModeData(RwCamera *cam, RwRect *rect)
{
float zero, xmax, ymax;
if(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){
2020-04-26 15:50:52 -04:00
zero = HALFPX;
xmax = rect->w + HALFPX;
ymax = rect->h + HALFPX;
2019-05-30 07:35:13 -04:00
}else{
2020-04-26 15:50:52 -04:00
zero = -HALFPX;
xmax = rect->w - HALFPX;
ymax = rect->h - HALFPX;
2019-05-30 07:35:13 -04:00
}
RwIm2DVertexSetScreenX(&Vertex[0], zero);
RwIm2DVertexSetScreenY(&Vertex[0], zero);
RwIm2DVertexSetScreenZ(&Vertex[0], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[0], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[0], 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetU(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, 255);
RwIm2DVertexSetScreenX(&Vertex[1], zero);
RwIm2DVertexSetScreenY(&Vertex[1], ymax);
RwIm2DVertexSetScreenZ(&Vertex[1], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[1], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[1], 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetU(&Vertex[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, 255);
RwIm2DVertexSetScreenX(&Vertex[2], xmax);
RwIm2DVertexSetScreenY(&Vertex[2], ymax);
RwIm2DVertexSetScreenZ(&Vertex[2], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[2], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[2], 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetU(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, 255);
RwIm2DVertexSetScreenX(&Vertex[3], xmax);
RwIm2DVertexSetScreenY(&Vertex[3], zero);
RwIm2DVertexSetScreenZ(&Vertex[3], RwIm2DGetNearScreenZ());
RwIm2DVertexSetCameraZ(&Vertex[3], RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetRecipCameraZ(&Vertex[3], 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetU(&Vertex[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetV(&Vertex[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, 255);
}
void
2020-06-29 06:12:52 -04:00
CMBlur::MotionBlurRender(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha)
2019-05-30 07:35:13 -04:00
{
2020-08-13 12:14:24 -04:00
#ifdef EXTENDED_COLOURFILTER
CPostFX::Render(cam, red, green, blue, blur, type, bluralpha);
#else
2019-06-30 06:53:39 -04:00
RwRGBA color = { (RwUInt8)red, (RwUInt8)green, (RwUInt8)blue, (RwUInt8)blur };
2020-06-27 17:01:51 -04:00
#ifdef GTA_PS2
if( pFrontBuffer )
2020-06-29 06:12:52 -04:00
OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
2020-06-27 17:01:51 -04:00
#else
2019-05-30 07:35:13 -04:00
if(BlurOn){
if(pFrontBuffer){
if(ms_bJustInitialised)
ms_bJustInitialised = false;
else
2020-06-29 06:12:52 -04:00
OverlayRender(cam, pFrontBuffer, color, type, bluralpha);
2019-05-30 07:35:13 -04:00
}
RwRasterPushContext(pFrontBuffer);
RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
RwRasterPopContext();
}else{
2020-06-29 06:12:52 -04:00
OverlayRender(cam, nil, color, type, bluralpha);
2019-05-30 07:35:13 -04:00
}
2020-06-27 17:01:51 -04:00
#endif
2020-08-13 12:14:24 -04:00
#endif
2019-05-30 07:35:13 -04:00
}
void
2020-06-29 06:12:52 -04:00
CMBlur::OverlayRender(RwCamera *cam, RwRaster *raster, RwRGBA color, int32 type, int32 bluralpha)
2019-05-30 07:35:13 -04:00
{
int r, g, b, a;
r = color.red;
g = color.green;
b = color.blue;
a = color.alpha;
DefinedState();
2020-06-27 17:01:51 -04:00
switch(type)
{
case MOTION_BLUR_SECURITY_CAM:
2019-05-30 07:35:13 -04:00
r = 0;
g = 255;
b = 0;
a = 128;
break;
2020-06-27 17:01:51 -04:00
case MOTION_BLUR_INTRO:
2019-05-30 07:35:13 -04:00
r = 100;
g = 220;
b = 230;
a = 158;
break;
2020-06-27 17:01:51 -04:00
case MOTION_BLUR_INTRO2:
2019-05-30 07:35:13 -04:00
r = 80;
g = 255;
b = 230;
a = 138;
break;
2020-06-27 17:01:51 -04:00
case MOTION_BLUR_INTRO3:
2019-05-30 07:35:13 -04:00
r = 255;
g = 60;
b = 60;
a = 200;
break;
2020-06-27 17:01:51 -04:00
case MOTION_BLUR_INTRO4:
2019-05-30 07:35:13 -04:00
r = 255;
g = 180;
b = 180;
a = 128;
break;
}
if(!BlurOn){
2020-06-27 17:01:51 -04:00
r = Min(r*0.6f, 255.0f);
g = Min(g*0.6f, 255.0f);
b = Min(b*0.6f, 255.0f);
if(type != MOTION_BLUR_SNIPER)
a = Min(a*0.6f, 255.0f);
2019-05-30 07:35:13 -04:00
// game clamps to 255 here, but why?
}
RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);
RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);
RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);
RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);
RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, BlurOn ? raster : nil);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
2020-06-29 06:12:52 -04:00
a = bluralpha/2;
2019-05-30 07:35:13 -04:00
if(a < 30)
a = 30;
if(BlurOn && a != 0){ // the second condition should always be true
RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, a);
RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, a);
RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, a);
RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, a);
RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
}
RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
}