dolphin/Source/Plugins/Plugin_VideoDX9/Src/D3DPostprocess.cpp

238 lines
6.2 KiB
C++

#include "Common.h"
#include "D3DBase.h"
#include "D3DTexture.h"
#include "D3DUtil.h"
#include "Globals.h"
using namespace D3D;
namespace Postprocess
{
LPDIRECT3DSURFACE9 displayColorBuffer;
LPDIRECT3DSURFACE9 displayZStencilBuffer;
LPDIRECT3DTEXTURE9 mainColorBufferTexture;
LPDIRECT3DSURFACE9 mainColorBuffer;
LPDIRECT3DSURFACE9 mainZStencilBuffer;
const int numScratch = 2;
LPDIRECT3DTEXTURE9 scratch[numScratch];
LPDIRECT3DSURFACE9 scratchSurface[numScratch];
const int mainWidth = 640, mainHeight=480;
const int scratchWidth = 256, scratchHeight=256;
int displayWidth, displayHeight;
bool initialized;
int GetWidth() {
return initialized ? mainWidth : displayWidth;
}
int GetHeight() {
return initialized ? mainHeight : displayHeight;
}
void CreateStuff()
{
mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight);
mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer);
mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight);
for (int i=0; i<numScratch; i++)
{
scratch[i]=D3D::CreateRenderTarget(scratchWidth,scratchHeight);
scratch[i]->GetSurfaceLevel(0,&(scratchSurface[i]));
}
initialized=true;
}
void DestroyStuff()
{
SAFE_RELEASE(mainColorBuffer);
SAFE_RELEASE(mainColorBufferTexture);
SAFE_RELEASE(mainZStencilBuffer);
for (int i=0; i<numScratch; i++)
{
SAFE_RELEASE(scratch[i]);
SAFE_RELEASE(scratchSurface[i]);
}
initialized=false;
}
void Initialize()
{
dev->GetRenderTarget(0,&displayColorBuffer);
dev->GetDepthStencilSurface(&displayZStencilBuffer);
D3DSURFACE_DESC desc;
displayColorBuffer->GetDesc(&desc);
displayWidth = desc.Width;
displayHeight = desc.Height;
if (g_Config.iPostprocessEffect)
CreateStuff();
}
void Cleanup()
{
DestroyStuff();
SAFE_RELEASE(displayColorBuffer);
SAFE_RELEASE(displayZStencilBuffer);
}
void BeginFrame()
{
if (g_Config.iPostprocessEffect)
{
if (!initialized)
CreateStuff();
dev->SetRenderTarget(0,mainColorBuffer);
dev->SetDepthStencilSurface(mainZStencilBuffer);
dev->SetRenderState(D3DRS_ZENABLE,TRUE);
dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0);
}
else
{
if (initialized)
{
dev->SetRenderTarget(0,displayColorBuffer);
dev->SetDepthStencilSurface(displayZStencilBuffer);
DestroyStuff();
}
dev->SetRenderState(D3DRS_ZENABLE,TRUE);
}
}
int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //goodlooking almostgaussian
//int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter
void NightGlow(bool intense, bool original)
{
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT);
dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
dev->SetDepthStencilSurface(0);
dev->SetTexture(0,mainColorBufferTexture);
dev->SetRenderTarget(0,scratchSurface[0]);
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
POINT pt;
GetCursorPos(&pt);
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f);
#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff);
float f=0.008f;
QOFF(0,0,0xa0a0a0a0);
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
dev->SetTexture(0,scratch[0]);
dev->SetRenderTarget(0,scratchSurface[1]);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
float yMul = 1.33333333333f;
for (int i=0; i<8; i++)
{
DWORD c=filterKernel[i]/2;
c|=c<<8;
c|=c<<16;
QOFF(0,(i-3.5f) * f * yMul,c);
}
dev->SetTexture(0,scratch[1]);
dev->SetRenderTarget(0,scratchSurface[0]);
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
for (int i=0; i<8; i++)
{
DWORD c=filterKernel[i]/(intense?3:2);
c|=c<<8;
c|=c<<16;
QOFF((i-3.5f) * f,0,c);
}
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
if (intense)
{
dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA);
}
else
{
dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR);
dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
}
dev->SetTexture(0,scratch[0]);
dev->SetRenderTarget(0,mainColorBuffer);
quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1);
dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0);
}
const char **GetPostprocessingNames()
{
static const char *names[] = {
"None",
"Night Glow 1",
"Night Glow 2",
"Night Glow 3",
0,
};
return names;
}
void FinalizeFrame()
{
if (initialized)
{
dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
dev->SetRenderState(D3DRS_ZENABLE,FALSE);
dev->SetRenderState(D3DRS_FOGENABLE,FALSE);
dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
switch(g_Config.iPostprocessEffect) {
case 1:
NightGlow(true,true);
case 2:
NightGlow(false,true);
break;
case 3:
NightGlow(false,false);
break;
}
dev->SetRenderTarget(0,displayColorBuffer);
dev->SetDepthStencilSurface(displayZStencilBuffer);
dev->SetTexture(0,mainColorBufferTexture);
quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF);
}
}
}