xbox-kernel/private/ntos/ani2/GreenFog.cpp
2020-09-30 17:17:25 +02:00

436 lines
15 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// File: GreenFog.cpp
//
// Copyright 2001 Pipeworks Software
///////////////////////////////////////////////////////////////////////////////
#include "precomp.h"
#include "xbs_math.h"
#include "xbs_app.h"
#include "qrand.h"
#include "GreenFog.h"
#include "tex_gen.h"
///////////////////////////////////////////////////////////////////////////////
#define PLASMA_SIZE (256)
// 1024x512 appears to be only .1 fps slower than 512x256.
#define INTENSITY_TEX_X (1024)
#define INTENSITY_TEX_Y (512)
//MTS#define INTENSITY_TEX_X (512)
//MTS#define INTENSITY_TEX_Y (256)
const float MUL_SCALE = 0.005f;
const float MAIN_FOG_RAD = 40.0f;
///////////////////////////////////////////////////////////////////////////////
void GreenFog::Init()
{
pQuadVB = NULL;
pIntensityQuadVB = NULL;
for (int i=0; i<NUM_PLASMAS; i++) pPlasmaTexture[i] = NULL;
pIntensityTextureU = pIntensityTextureR = NULL;
pIntensityZ = NULL;
dwFogPShader = dwFogVShader = 0;
}
///////////////////////////////////////////////////////////////////////////////
void GreenFog::create()
{
destroy();
const float f_plasma_dim = ((float)PLASMA_SIZE);
gpd3dDev->CreateTexture(INTENSITY_TEX_X, INTENSITY_TEX_Y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, 0, &pIntensityTextureU);
gpd3dDev->CreateTexture(INTENSITY_TEX_X, INTENSITY_TEX_Y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, 0, &pIntensityTextureR);
gpd3dDev->CreateDepthStencilSurface(INTENSITY_TEX_X,INTENSITY_TEX_Y,D3DFMT_LIN_D24S8, D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR , &pIntensityZ);
gpd3dDev->CreateVertexBuffer(4*sizeof(GreenFogVertexBuffer), 0, 0, 0, &pQuadVB);
GreenFogVertexBuffer* p_verts;
pQuadVB->Lock(0, 0, (BYTE**) &p_verts, 0);
Set(&p_verts[0].pos, -1.0f, -1.0f, 1.0f);
Set(&p_verts[1].pos, -1.0f, +1.0f, 1.0f);
Set(&p_verts[2].pos, +1.0f, +1.0f, 1.0f);
Set(&p_verts[3].pos, +1.0f, -1.0f, 1.0f);
p_verts[0].tu0 = 0.0f; p_verts[0].tv0 = 1.0f;
p_verts[1].tu0 = 0.0f; p_verts[1].tv0 = 0.0f;
p_verts[2].tu0 = 1.0f; p_verts[2].tv0 = 0.0f;
p_verts[3].tu0 = 1.0f; p_verts[3].tv0 = 1.0f;
for (int i=0; i<4; i++)
{
p_verts[i].tv1 = -(2.0f*p_verts[i].tu0 - 1.0f) * 640.0f/f_plasma_dim;
p_verts[i].tu1 = -(2.0f*p_verts[i].tv0 - 1.0f) * 480.0f/f_plasma_dim;
//MTS p_verts[i].tu1 = (2.0f*p_verts[i].tu0 - 1.0f) * 640.0f/f_plasma_dim;
//MTS p_verts[i].tv1 = (2.0f*p_verts[i].tv0 - 1.0f) * 480.0f/f_plasma_dim;
}
pQuadVB->Unlock();
// These are used to render the backdrop.
gpd3dDev->CreateVertexBuffer(4*sizeof(BaseStream), 0, 0, 0, &pIntensityQuadVB);
BaseStream* p_bs_verts;
pIntensityQuadVB->Lock(0, 0, (BYTE**) &p_bs_verts, 0);
Set(&p_bs_verts[0].p, -1.0f, -1.0f, 1.0f);
Set(&p_bs_verts[1].p, -1.0f, +1.0f, 1.0f);
Set(&p_bs_verts[2].p, +1.0f, +1.0f, 1.0f);
Set(&p_bs_verts[3].p, +1.0f, -1.0f, 1.0f);
pIntensityQuadVB->Unlock();
DWORD dwShaderVertexDecl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // position
D3DVSD_REG( 1, D3DVSDT_FLOAT2 ), // intensity texture
D3DVSD_REG( 2, D3DVSDT_FLOAT2 ), // plasma 0
D3DVSD_END()
};
#ifndef BINARY_RESOURCE
dwFogPShader = gApp.loadPixelShader( "d:\\shaders\\greenfog.xpu" );
dwFogVShader = gApp.loadVertexShader( "d:\\shaders\\greenfog.xvu", dwShaderVertexDecl );
#else // BINARY_RESOURCE
dwFogPShader = gApp.loadPixelShader( g_greenfog_xpu );
dwFogVShader = gApp.loadVertexShader( g_greenfog_xvu, dwShaderVertexDecl );
#endif // BINARY_RESOURCE
restart(); // renders the texture
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void GreenFog::destroy()
{
#define XBS_RESOURCE_RELEASE(a) if (a) a->Release(); a = NULL;
XBS_RESOURCE_RELEASE(pQuadVB);
XBS_RESOURCE_RELEASE(pIntensityQuadVB);
for (int i=0; i<NUM_PLASMAS; i++) { XBS_RESOURCE_RELEASE(pPlasmaTexture[i]); }
XBS_RESOURCE_RELEASE(pIntensityTextureU);
XBS_RESOURCE_RELEASE(pIntensityTextureR);
XBS_RESOURCE_RELEASE(pIntensityZ);
#undef XBS_RESOURCE_RELEASE
if (dwFogPShader) gpd3dDev->DeletePixelShader( dwFogPShader );
if (dwFogVShader) gpd3dDev->DeleteVertexShader( dwFogVShader );
dwFogPShader = dwFogVShader = 0;
}
///////////////////////////////////////////////////////////////////////////////
void GreenFog::advanceTime(float fElapsedTime, float fDt)
{
renderIntensityTexture();
}
///////////////////////////////////////////////////////////////////////////////
void GreenFog::render(bool b_cmp_to_one)
{
int i;
gpd3dDev->SetVertexShader( dwFogVShader );
gpd3dDev->SetPixelShader ( dwFogPShader );
// Swap render and update textures.
LPDIRECT3DTEXTURE8 p_swap = pIntensityTextureR;
pIntensityTextureR = pIntensityTextureU;
pIntensityTextureU = p_swap;
// Use what was the update(d) texture.
gpd3dDev->SetTexture(0, pIntensityTextureR);
gpd3dDev->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_NONE );
gpd3dDev->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP);
gpd3dDev->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP);
for (i=0; i<NUM_PLASMAS; i++)
{
gpd3dDev->SetTexture(i+1, pPlasmaTexture[i]);
gpd3dDev->SetTextureStageState( i+1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( i+1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
gpd3dDev->SetTextureStageState( i+1, D3DTSS_MIPFILTER, D3DTEXF_NONE );
gpd3dDev->SetTextureStageState( i+1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
gpd3dDev->SetTextureStageState( i+1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
}
gpd3dDev->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
//MTS gpd3dDev->SetRenderState( D3DRS_ZFUNC, D3DCMP_GREATEREQUAL );
gpd3dDev->SetRenderState( D3DRS_ZFUNC, (b_cmp_to_one) ? D3DCMP_EQUAL : D3DCMP_ALWAYS );
gpd3dDev->SetRenderState( D3DRS_ALPHAREF, 0x00000001 );
gpd3dDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
gpd3dDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
//MTS gpd3dDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE ); // Just render intensity
//MTS gpd3dDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ZERO ); // Just render intensity
gpd3dDev->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );
D3DVECTOR4 val[2*NUM_PLASMAS];
float f_intensity = max(0.0f, gApp.getBlobIntensity() * 0.7f - 0.1f);
Set(&val[0], 0.0f*f_intensity, f_intensity, 0.0f*f_intensity, 1.0f);
float f_glow = 0.75f * max(0.0f, min(1.0f, (gApp.getElapsedTime() - GLOW_FADE_SCREEN_START) * GLOW_FADE_SCREEN_MUL));
//MTS Set(&val[1], f_glow*0.625f, f_glow*1.0f, f_glow*0.0625f, 0.0f);
Set(&val[1], f_glow*0.625f, f_glow, f_glow * 0.4f, 0.0f);
gpd3dDev->SetPixelShaderConstant(0, &val[0], 2);
D3DVECTOR4 origin, origin_scr;
Set(&origin, 0.0f, 0.0f, 0.0f, 1.0f);
TransformPoint(origin, gApp.theCamera.getWTP(), &origin_scr);
Scale(&origin_scr, 1.0f / origin_scr.w);
const float f_plasma_dim = ((float)PLASMA_SIZE);
// Set the transforms for the plasma texture coordinates.
for (i=0; i<NUM_PLASMAS; i++)
{
float rad = 0.6f * (((float)(NUM_PLASMAS-i-1)) / ((float)NUM_PLASMAS) - 0.2f);
float x_mul = 0.5f * gApp.getCameraRadiusFromBlob() * MUL_SCALE;
float y_mul = 1.0f * gApp.theCamera.getAspectRatio() * gApp.getCameraRadiusFromBlob() * MUL_SCALE;
float x_add = rad * gApp.getCameraTheta() - origin_scr.x * x_mul * 640.0f/f_plasma_dim;
float y_add = -rad * gApp.getCameraPhi() + origin_scr.y * y_mul * 480.0f/f_plasma_dim;
// I don't know why y_mul is 1.0f* and x_mul is 0.5f*, but it looks less stretched in y this way.
Set(&val[2*i+0], y_add, x_add, 0.0f, 0.0f);
Set(&val[2*i+1], -y_mul, -x_mul, 1.0f, 1.0f);
//MTS Set(&val[2*i+0], x_add, y_add, 0.0f, 0.0f);
//MTS Set(&val[2*i+1], x_mul, y_mul, 1.0f, 1.0f);
}
gpd3dDev->SetVertexShaderConstant(0, &val[0], 2*NUM_PLASMAS);
gpd3dDev->SetStreamSource(0, pQuadVB, sizeof(GreenFogVertexBuffer));
gpd3dDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
gpd3dDev->SetPixelShader (NULL);
gpd3dDev->SetVertexShader(NULL);
for (i=0; i<1+NUM_PLASMAS; i++) gpd3dDev->SetTexture(i, NULL);
// Render fade to yellow.
f_glow = max(0.0f, min(1.0f, (gApp.getElapsedTime() - GLOW_FADE_CIRCLE_START) * GLOW_FADE_CIRCLE_MUL));
if (gApp.getElapsedTime() < BLOB_STATIC_END_TIME)
{
float t = gApp.getElapsedTime();
f_glow = (t < BLOB_STATIC_END_TIME * 0.2f) ? (t / (BLOB_STATIC_END_TIME*0.2f)) : (1.0f - (t-BLOB_STATIC_END_TIME * 0.2f)/BLOB_STATIC_END_TIME);
}
int alpha = max(0, min( 255, (int) ((255.0f * f_glow))));
//MTS alpha >>= 1;
alpha = min(196, alpha*2);
if (alpha)
{
//MTS DWORD glow_factor = 0x00a0ff10 | (alpha << 24);
DWORD glow_factor = 0x00A0FF60 | (alpha << 24);
gpd3dDev->SetRenderState(D3DRS_TEXTUREFACTOR, glow_factor);
gpd3dDev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TFACTOR);
gpd3dDev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_TEXTURE);
gpd3dDev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
gpd3dDev->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_DISABLE);
gpd3dDev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TFACTOR);
gpd3dDev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_TEXTURE);
gpd3dDev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
// Correct center.
float x_mul = gApp.getCameraRadiusFromBlob() * MUL_SCALE;
float y_mul = gApp.getCameraRadiusFromBlob() * MUL_SCALE * gApp.theCamera.getAspectRatio();
D3DVECTOR4 origin, origin_screen;
Set(&origin, 0.0f, 0.0f, 0.0f, 1.0f);
TransformPoint(origin, gApp.theCamera.getWTP(), &origin_screen);
Scale(&origin_screen, 1.0f / origin_screen.w);
//origin_screen.x = 0.5f - x_mul * origin_screen.x;
//origin_screen.y = 0.5f - y_mul * origin_screen.y;
D3DMATRIX mat_tex;
float mul = 0.33f / f_glow;
if (gApp.getElapsedTime() < BLOB_STATIC_END_TIME)
{
mul = gApp.getCameraRadiusFromBlob() * BLOB_STATIC_END_TIME / (gApp.getElapsedTime() * 8.0f);
}
SetScale(mul, mul, 1.0f, &mat_tex);
mat_tex._31 = 0.5f*(1.0f-mul) - 0.5f * origin_screen.x * mul * 1.33f;
mat_tex._32 = 0.5f*(1.0f-mul) + 0.5f * origin_screen.y * mul;
D3DMATRIX iden,scaled;
SetIdentity(&iden);
SetScale(1.0f / mul, 1.0f / mul, 0.0f, &scaled);
scaled._43 = 1.0f;
gpd3dDev->SetTransform(D3DTS_WORLD, &scaled);
gpd3dDev->SetTransform(D3DTS_VIEW, &iden);
gpd3dDev->SetTransform(D3DTS_PROJECTION, &iden);
gpd3dDev->SetTexture(0,gApp.pGlowMap);
gpd3dDev->SetVertexShader(D3DFVF_XYZ | D3DFVF_TEX2);
gpd3dDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
}
gpd3dDev->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
gpd3dDev->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
}
///////////////////////////////////////////////////////////////////////////////
void GreenFog::restart()
{
int tffonp = 255 / NUM_PLASMAS;
for (int i=0; i<NUM_PLASMAS; i++)
{
if (pPlasmaTexture[i]) pPlasmaTexture[i]->Release();
}
CreateIntensityTexture_8Bit(pPlasmaTexture, NUM_PLASMAS, PLASMA_SIZE, 5 * tffonp, gApp.rand(),
((tffonp*3)/4) << 8, 255/max(1,NUM_PLASMAS-0));
}
///////////////////////////////////////////////////////////////////////////////
void GreenFog::renderIntensityTexture()
{
// Get camera position and render geometry into background.
// Store old render targets.
LPDIRECT3DSURFACE8 pOldRT,pOldZ;
gpd3dDev->GetRenderTarget(&pOldRT);
gpd3dDev->GetDepthStencilSurface(&pOldZ);
// Leave the camera position where it is.
LPDIRECT3DSURFACE8 p_update_surf;
pIntensityTextureU->GetSurfaceLevel(0, &p_update_surf);
gpd3dDev->SetRenderTarget(p_update_surf, pIntensityZ);
if( gpd3dDev->BeginScene() == D3D_OK )
{
gpd3dDev->Clear(0,NULL,
D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET,
0xffff0000,
1.f,
0 );
// Render a backdrop.
gpd3dDev->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
gpd3dDev->SetRenderState( D3DRS_ALPHAREF, 0x00000001 );
gpd3dDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
gpd3dDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
gpd3dDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ZERO );
gpd3dDev->SetVertexShader(gApp.dwVShader[st_Depth]);
gpd3dDev->SetPixelShader (gApp.dwPShader[st_Depth]);
//#define Z_ADD c16
//#define Z_MUL c17
//#define POS_MUL c18
//#define POS_SHIFT c19
D3DVECTOR4 val[4];
float max_color_dist = 2.0f * MAIN_FOG_RAD;
float z_mul = 1.0f; // set later on for the geometry case, this is just the backdrop
float z_add = 0.0f;
Set(&val[0], z_mul, z_mul, z_mul, 1.0f );
Set(&val[1], z_add, z_add, z_add, 1.0f );
float x_mul = gApp.getCameraRadiusFromBlob() * MUL_SCALE;
float y_mul = gApp.getCameraRadiusFromBlob() * MUL_SCALE * gApp.theCamera.getAspectRatio();
Set(&val[2], x_mul, y_mul, 0.0f, 1.0f);
D3DVECTOR4 origin;
Set(&origin, 0.0f, 0.0f, 0.0f, 1.0f);
TransformPoint(origin, gApp.theCamera.getWTP(), &val[3]);
Scale(&val[3], 1.0f / val[3].w);
val[3].x = 0.5f - val[2].x * val[3].x;
val[3].y = 0.5f - val[2].y * val[3].y;
val[3].z = 0.5f;
val[3].w = 0.0f;
// If looking at origin, then Set(&val[3], 0.5f, 0.5f, 0.5f, 0.0f);
//MTS Set(&val[3], 0.5f, 0.5f, 0.5f, 0.0f);
gpd3dDev->SetVertexShaderConstant(16, &val[0], 4);
D3DMATRIX iden;
SetIdentity(&iden);
iden._43 = 1.0f;
iden._44 = 0.0f;
gpd3dDev->SetVertexShaderConstant(0, &iden, 4);
gpd3dDev->SetStreamSource(0, pIntensityQuadVB, sizeof(BaseStream));
gpd3dDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
gpd3dDev->SetRenderState( D3DRS_ZWRITEENABLE, TRUE);
gpd3dDev->SetRenderState( D3DRS_ZENABLE, TRUE);
z_add = MAIN_FOG_RAD - gApp.getCameraRadiusFromBlob();
z_mul = 1.0f / max_color_dist;
Set(&val[0], z_mul, z_mul, z_mul, 1.0f );
Set(&val[1], z_add, z_add, z_add, 1.0f );
gpd3dDev->SetVertexShaderConstant(16, &val, 2);
gApp.sceneGeom.renderZ();
// Without NULLing the pixel shader, the shields aren't transparent. Dunno why.
gpd3dDev->SetPixelShader (NULL);
gpd3dDev->SetVertexShader(NULL);
// Clear stencil and depth buffer, but not the "target", or ARGB values.
gpd3dDev->Clear(0,NULL,
D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER,
0xffffffff,
1.f,
0 );
gpd3dDev->EndScene();
}
else
{
int a = 0;
}
gpd3dDev->SetRenderTarget(pOldRT,pOldZ);
p_update_surf->Release();
pOldRT->Release();
pOldZ->Release();
}
///////////////////////////////////////////////////////////////////////////////