aboutsummaryrefslogtreecommitdiffstats
path: root/src/extras/postfx.cpp
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2020-08-11 18:39:53 +0200
committeraap <aap@papnet.eu>2020-08-11 18:40:04 +0200
commitb468d010a8a185bd04cdb1fb41810a189971e583 (patch)
tree8eda0c65a57dd11653252fcca2bbbd64c9343b5c /src/extras/postfx.cpp
parentc3443bff992e36c1675aebd536dbfaf21bc6aaa8 (diff)
implemented extended postfx
Diffstat (limited to 'src/extras/postfx.cpp')
-rw-r--r--src/extras/postfx.cpp516
1 files changed, 516 insertions, 0 deletions
diff --git a/src/extras/postfx.cpp b/src/extras/postfx.cpp
new file mode 100644
index 00000000..e8cd4bc4
--- /dev/null
+++ b/src/extras/postfx.cpp
@@ -0,0 +1,516 @@
+#define WITHWINDOWS
+#define WITH_D3D
+#include "common.h"
+
+#ifdef EXTENDED_COLOURFILTER
+
+#ifndef LIBRW
+#error "Need librw for EXTENDED_COLOURFILTER"
+#endif
+
+#include "RwHelper.h"
+#include "Camera.h"
+#include "MBlur.h"
+#include "postfx.h"
+
+RwRaster *CPostFX::pFrontBuffer;
+RwRaster *CPostFX::pBackBuffer;
+bool CPostFX::bJustInitialised;
+int CPostFX::EffectSwitch = POSTFX_NORMAL;
+bool CPostFX::BlurOn = false;
+bool CPostFX::MotionBlurOn = false;
+
+static RwIm2DVertex Vertex[4];
+static RwIm2DVertex Vertex2[4];
+static RwImVertexIndex Index[6] = { 0, 1, 2, 0, 2, 3 };
+
+#ifdef RW_D3D9
+void *colourfilterVC_PS;
+void *contrast_PS;
+#endif
+#ifdef RW_OPENGL
+int32 u_blurcolor;
+int32 u_contrastAdd;
+int32 u_contrastMult;
+rw::gl3::Shader *colourFilterVC;
+rw::gl3::Shader *contrast;
+#endif
+
+void
+CPostFX::InitOnce(void)
+{
+#ifdef RW_OPENGL
+ u_blurcolor = rw::gl3::registerUniform("u_blurcolor");
+ u_contrastAdd = rw::gl3::registerUniform("u_contrastAdd");
+ u_contrastMult = rw::gl3::registerUniform("u_contrastMult");
+#endif
+}
+
+void
+CPostFX::Open(RwCamera *cam)
+{
+ 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));
+ pFrontBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE);
+ pBackBuffer = RwRasterCreate(width, height, depth, rwRASTERTYPECAMERATEXTURE);
+ bJustInitialised = true;
+
+ float zero, xmax, ymax;
+
+ if(RwRasterGetDepth(RwCameraGetRaster(cam)) == 16){
+ zero = HALFPX;
+ xmax = width + HALFPX;
+ ymax = height + HALFPX;
+ }else{
+ zero = -HALFPX;
+ xmax = width - HALFPX;
+ ymax = height - HALFPX;
+ }
+
+ 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);
+
+
+ RwIm2DVertexSetScreenX(&Vertex2[0], zero + 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[0], zero + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[0], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[0], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[0], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[0], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX(&Vertex2[1], 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[1], ymax + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[1], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[1], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[1], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[1], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[1], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX(&Vertex2[2], xmax + 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[2], ymax + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[2], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[2], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[2], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[2], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], 255, 255, 255, 255);
+
+ RwIm2DVertexSetScreenX(&Vertex2[3], xmax + 2.0f);
+ RwIm2DVertexSetScreenY(&Vertex2[3], zero + 2.0f);
+ RwIm2DVertexSetScreenZ(&Vertex2[3], RwIm2DGetNearScreenZ());
+ RwIm2DVertexSetCameraZ(&Vertex2[3], RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetRecipCameraZ(&Vertex2[3], 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetU(&Vertex2[3], 1.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetV(&Vertex2[3], 0.0f, 1.0f/RwCameraGetNearClipPlane(cam));
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], 255, 255, 255, 255);
+
+
+#ifdef RW_D3D9
+#include "shaders/colourfilterVC_PS.inc"
+ colourfilterVC_PS = rw::d3d::createPixelShader(colourfilterVC_PS_cso);
+#include "shaders/contrastPS.inc"
+ contrast_PS = rw::d3d::createPixelShader(contrastPS_cso);
+#endif
+#ifdef RW_OPENGL
+ using namespace rw::gl3;
+// AllocConsole();
+// freopen("CONIN$", "r", stdin);
+// freopen("CONOUT$", "w", stdout);
+// freopen("CONOUT$", "w", stderr);
+
+
+ {
+#ifdef RW_GLES2
+#include "gl2_shaders/im2d_gl2.inc"
+#include "gl2_shaders/colourfilterVC_fs_gl2.inc"
+#else
+#include "shaders/im2d_gl3.inc"
+#include "shaders/colourfilterVC_fs_gl3.inc"
+#endif
+ const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, colourfilterVC_frag_src, nil };
+ colourFilterVC = Shader::create(vs, fs);
+ assert(colourFilterVC);
+ }
+
+ {
+#ifdef RW_GLES2
+#include "gl2_shaders/im2d_gl2.inc"
+#include "gl2_shaders/contrast_fs_gl2.inc"
+#else
+#include "shaders/im2d_gl3.inc"
+#include "shaders/contrast_fs_gl3.inc"
+ const char *vs[] = { shaderDecl, header_vert_src, im2d_vert_src, nil };
+ const char *fs[] = { shaderDecl, header_frag_src, contrast_frag_src, nil };
+ contrast = Shader::create(vs, fs);
+ assert(contrast);
+#endif
+ }
+
+#endif
+}
+
+void
+CPostFX::Close(void)
+{
+ if(pFrontBuffer){
+ RwRasterDestroy(pFrontBuffer);
+ pFrontBuffer = nil;
+ }
+ if(pBackBuffer){
+ RwRasterDestroy(pBackBuffer);
+ pBackBuffer = nil;
+ }
+#ifdef RW_D3D9
+ if(colourfilterVC_PS){
+ rw::d3d::destroyPixelShader(colourfilterVC_PS);
+ colourfilterVC_PS = nil;
+ }
+ if(contrast_PS){
+ rw::d3d::destroyPixelShader(contrast_PS);
+ contrast_PS = nil;
+ }
+#endif
+#ifdef RW_OPENGL
+ if(colourFilterVC){
+ colourFilterVC->destroy();
+ colourFilterVC = nil;
+ }
+ if(contrast){
+ contrast->destroy();
+ contrast = nil;
+ }
+#endif
+}
+
+void
+CPostFX::RenderOverlayBlur(RwCamera *cam, int32 r, int32 g, int32 b, int32 a)
+{
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, pFrontBuffer);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+
+ RwIm2DVertexSetIntRGBA(&Vertex[0], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r*2, g*2, b*2, 30);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r*2, g*2, b*2, 30);
+
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, BlurOn ? Vertex2 : Vertex, 4, Index, 6);
+
+
+ RwIm2DVertexSetIntRGBA(&Vertex2[0], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[1], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[2], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex2[3], r, g, b, a);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, a);
+
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, BlurOn ? Vertex2 : Vertex, 4, Index, 6);
+}
+
+void
+CPostFX::RenderOverlaySniper(RwCamera *cam, int32 r, int32 g, int32 b, int32 a)
+{
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, pFrontBuffer);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+
+ RwIm2DVertexSetIntRGBA(&Vertex[0], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], r, g, b, 80);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], r, g, b, 80);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+}
+
+float CPostFX::Intensity = 1.0f;
+
+void
+CPostFX::RenderOverlayShader(RwCamera *cam, int32 r, int32 g, int32 b, int32 a)
+{
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, pBackBuffer);
+
+ if(EffectSwitch == POSTFX_MOBILE){
+ float mult[3], add[3];
+ mult[0] = (r-64)/256.0f + 1.4f;
+ mult[1] = (g-64)/256.0f + 1.4f;
+ mult[2] = (b-64)/256.0f + 1.4f;
+ add[0] = r/1536.f - 0.05f;
+ add[1] = g/1536.f - 0.05f;
+ add[2] = b/1536.f - 0.05f;
+#ifdef RW_D3D9
+ rw::d3d::d3ddevice->SetPixelShaderConstantF(10, mult, 1);
+ rw::d3d::d3ddevice->SetPixelShaderConstantF(11, add, 1);
+
+ rw::d3d::im2dOverridePS = contrast_PS;
+#endif
+#ifdef RW_OPENGL
+ rw::gl3::im2dOverrideShader = contrast;
+ contrast->use();
+ glUniform3fv(contrast->uniformLocations[u_contrastMult], 1, mult);
+ glUniform3fv(contrast->uniformLocations[u_contrastAdd], 1, add);
+#endif
+ }else{
+ float f = Intensity;
+ float blurcolors[4];
+ blurcolors[0] = r*f/255.0f;
+ blurcolors[1] = g*f/255.0f;
+ blurcolors[2] = b*f/255.0f;
+ blurcolors[3] = 30/255.0f;
+#ifdef RW_D3D9
+ rw::d3d::d3ddevice->SetPixelShaderConstantF(10, blurcolors, 1);
+
+/*
+ float blurcolors[NUMAVERAGE*4];
+ int j = Next;
+ for(int i = NUMAVERAGE-1; i >= 0; i--){
+ j = (j+NUMAVERAGE-1)%NUMAVERAGE;
+// blurcolors[i*4+0] = PrevRed[j]/255.0f;
+// blurcolors[i*4+1] = PrevGreen[j]/255.0f;
+// blurcolors[i*4+2] = PrevBlue[j]/255.0f;
+// blurcolors[i*4+3] = Intensity/255.0f;
+
+ blurcolors[i*4+0] = r/255.0f;
+ blurcolors[i*4+1] = g/255.0f;
+ blurcolors[i*4+2] = b/255.0f;
+ blurcolors[i*4+3] = Intensity/255.0f;
+ }
+ rw::d3d::d3ddevice->SetPixelShaderConstantF(15, blurcolors, NUMAVERAGE);
+*/
+
+ rw::d3d::im2dOverridePS = colourfilterVC_PS;
+#endif
+#ifdef RW_OPENGL
+ rw::gl3::im2dOverrideShader = colourFilterVC;
+ colourFilterVC->use();
+ glUniform4fv(colourFilterVC->uniformLocations[u_blurcolor], 1, blurcolors);
+#endif
+ }
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+#ifdef RW_D3D9
+ rw::d3d::im2dOverridePS = nil;
+#endif
+#ifdef RW_OPENGL
+ rw::gl3::im2dOverrideShader = nil;
+#endif
+}
+
+void
+CPostFX::RenderMotionBlur(RwCamera *cam, uint32 blur)
+{
+ if(blur == 0)
+ return;
+
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, pFrontBuffer);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
+ RwIm2DVertexSetIntRGBA(&Vertex[0], 255, 255, 255, blur);
+ RwIm2DVertexSetIntRGBA(&Vertex[1], 255, 255, 255, blur);
+ RwIm2DVertexSetIntRGBA(&Vertex[2], 255, 255, 255, blur);
+ RwIm2DVertexSetIntRGBA(&Vertex[3], 255, 255, 255, blur);
+
+ RwIm2DRenderIndexedPrimitive(rwPRIMTYPETRILIST, Vertex, 4, Index, 6);
+}
+
+bool
+CPostFX::NeedBackBuffer(void)
+{
+ // Current frame -- needed for non-blur effect
+ switch(EffectSwitch){
+ case POSTFX_OFF:
+ case POSTFX_SIMPLE:
+ // no actual rendering here
+ return false;
+ case POSTFX_NORMAL:
+ if(MotionBlurOn)
+ return false;
+ else
+ return true;
+ case POSTFX_MOBILE:
+ return true;
+ }
+ return false;
+}
+
+bool
+CPostFX::NeedFrontBuffer(int32 type)
+{
+ // Last frame -- needed for motion blur
+ if(CMBlur::Drunkness > 0.0f)
+ return true;
+ if(type == MOTION_BLUR_SNIPER)
+ return true;
+
+ switch(EffectSwitch){
+ case POSTFX_OFF:
+ case POSTFX_SIMPLE:
+ // no actual rendering here
+ return false;
+ case POSTFX_NORMAL:
+ if(MotionBlurOn)
+ return true;
+ else
+ return false;
+ case POSTFX_MOBILE:
+ return false;
+ }
+ return false;
+}
+
+void
+CPostFX::Render(RwCamera *cam, uint32 red, uint32 green, uint32 blue, uint32 blur, int32 type, uint32 bluralpha)
+{
+ if(pFrontBuffer == nil)
+ Open(cam);
+ assert(pFrontBuffer);
+ assert(pBackBuffer);
+
+ if(type == MOTION_BLUR_LIGHT_SCENE){
+ SmoothColor(red, green, blue, blur);
+ red = AvgRed;
+ green = AvgGreen;
+ blue = AvgBlue;
+ blur = AvgAlpha;
+ }
+
+ if(NeedBackBuffer()){
+ RwRasterPushContext(pBackBuffer);
+ RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
+ RwRasterPopContext();
+ }
+
+ DefinedState();
+
+ RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATETEXTUREFILTER, (void*)rwFILTERNEAREST);
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
+
+ if(type == MOTION_BLUR_SNIPER){
+ if(!bJustInitialised)
+ RenderOverlaySniper(cam, red, green, blue, blur);
+ }else switch(EffectSwitch){
+ case POSTFX_OFF:
+ case POSTFX_SIMPLE:
+ // no actual rendering here
+ break;
+ case POSTFX_NORMAL:
+ if(MotionBlurOn){
+ if(!bJustInitialised)
+ RenderOverlayBlur(cam, red, green, blue, blur);
+ }else{
+ RenderOverlayShader(cam, red, green, blue, blur);
+ }
+ break;
+ case POSTFX_MOBILE:
+ RenderOverlayShader(cam, red, green, blue, blur);
+ break;
+ }
+
+ if(!bJustInitialised)
+ RenderMotionBlur(cam, 175.0f * CMBlur::Drunkness);
+
+ RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
+ RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
+ RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
+ RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
+ RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
+
+ if(NeedFrontBuffer(type)){
+ RwRasterPushContext(pFrontBuffer);
+ RwRasterRenderFast(RwCameraGetRaster(cam), 0, 0);
+ RwRasterPopContext();
+ bJustInitialised = false;
+ }else
+ bJustInitialised = true;
+}
+
+int CPostFX::PrevRed[NUMAVERAGE], CPostFX::AvgRed;
+int CPostFX::PrevGreen[NUMAVERAGE], CPostFX::AvgGreen;
+int CPostFX::PrevBlue[NUMAVERAGE], CPostFX::AvgBlue;
+int CPostFX::PrevAlpha[NUMAVERAGE], CPostFX::AvgAlpha;
+int CPostFX::Next;
+int CPostFX::NumValues;
+
+// This is rather annoying...the blur color can flicker slightly
+// which becomes very visible when amplified by the shader
+void
+CPostFX::SmoothColor(uint32 red, uint32 green, uint32 blue, uint32 alpha)
+{
+ PrevRed[Next] = red;
+ PrevGreen[Next] = green;
+ PrevBlue[Next] = blue;
+ PrevAlpha[Next] = alpha;
+ Next = (Next+1) % NUMAVERAGE;
+ NumValues = Min(NumValues+1, NUMAVERAGE);
+
+ AvgRed = 0;
+ AvgGreen = 0;
+ AvgBlue = 0;
+ AvgAlpha = 0;
+ for(int i = 0; i < NumValues; i++){
+ AvgRed += PrevRed[i];
+ AvgGreen += PrevGreen[i];
+ AvgBlue += PrevBlue[i];
+ AvgAlpha += PrevAlpha[i];
+ }
+ AvgRed /= NumValues;
+ AvgGreen /= NumValues;
+ AvgBlue /= NumValues;
+ AvgAlpha /= NumValues;
+}
+
+#endif