Files
FC1/RenderDll/XRenderD3D9/D3DShadows.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

1149 lines
37 KiB
C++

/*=============================================================================
D3DShadows.cpp : shadows support.
Copyright (c) 2001 Crytek Studios. All Rights Reserved.
Revision history:
* Created by Honich Andrey
=============================================================================*/
#include "RenderPCH.h"
#include "DriverD3D9.h"
#include <IEntityRenderState.h>
#include "../Common/Shadow_Renderer.h"
#include "../Common/RendElements/CREScreenCommon.h"
#include "D3DCGVProgram.h"
#include "D3DCGPShader.h"
#include "I3dengine.h"
void WriteTGA8(byte *data8, int width, int height, char *filename);
void BlurImage8(byte * pImage, int nSize, int nPassesNum);
void MakePenumbraTextureFromDepthMap(byte * pDepthMapIn, int nSize, byte * pPenumbraMapOut);
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
// Texture coordinate rectangle
struct CoordRect
{
float fLeftU, fTopV;
float fRightU, fBottomV;
};
HRESULT GetTextureRect(STexPic *pTexture, RECT* pRect);
HRESULT GetSampleOffsets_GaussBlur5x5(DWORD dwD3DTexWidth, DWORD dwD3DTexHeight, D3DXVECTOR4* avTexCoordOffset, D3DXVECTOR4* avSampleWeight, FLOAT fMultiplier);
HRESULT GetSampleOffsets_GaussBlur5x5Bilinear(DWORD dwD3DTexWidth, DWORD dwD3DTexHeight, D3DXVECTOR4* avTexCoordOffset, D3DXVECTOR4* avSampleWeight, FLOAT fMultiplier);
HRESULT GetTextureCoords( STexPic *pTexSrc, RECT* pRectSrc, STexPic *pTexDest, RECT* pRectDest, CoordRect* pCoords);
void CD3D9Renderer::BlurImage(int nSizeX, int nSizeY, int nType, ShadowMapTexInfo *st, int nTexDst)
{
IDirect3DSurface9 *pIRGBTargetSurf = NULL;
IDirect3DSurface9 *pIZBufferSurf = NULL;
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
LPDIRECT3DTEXTURE9 pIRGBTarget = NULL;
HRESULT hReturn;
STexPicD3D *tpSrc = (STexPicD3D *)m_TexMan->GetByID(st->nTexId0);
STexPicD3D *tpDst = (STexPicD3D *)m_TexMan->GetByID(nTexDst);
if (tpDst)
{
pID3DTexture = (LPDIRECT3DTEXTURE9)tpDst->m_RefTex.m_VidTex;
hReturn = pID3DTexture->GetSurfaceLevel(0, &pIRGBTargetSurf);
}
m_RP.m_PersFlags &= ~(RBPF_VSNEEDSET | RBPF_PS1NEEDSET);
m_RP.m_FlagsModificators = 0;
m_RP.m_CurrentVLights = 0;
m_RP.m_FlagsPerFlush = 0;
EF_CommitShadersState();
EF_CommitVLightsState();
m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
if (m_RP.m_TexStages[0].TCIndex != 0)
{
m_RP.m_TexStages[0].TCIndex = 0;
m_pd3dDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU | 0);
}
EF_Scissor(false, 0, 0, 0, 0);
SetCullMode(R_CULL_NONE);
CD3D9TexMan::BindNULL(1);
EF_SelectTMU(0);
if(tpSrc)
{
tpSrc->m_RefTex.m_MinFilter=D3DTEXF_LINEAR;
tpSrc->m_RefTex.m_MagFilter=D3DTEXF_LINEAR;
tpSrc->m_RefTex.bRepeats=false;
tpSrc->Set();
}
hReturn = m_pd3dDevice->SetRenderTarget(0, pIRGBTargetSurf);
EF_SetState(GS_NODEPTHTEST);
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
DrawQuad(0,0,(float)nSizeX,(float)nSizeY,Col_White,1);
if (nType == 1 || (nType > 1 && !(m_Features & RFT_HW_PS20)))
{
EF_SetState(GS_NODEPTHTEST | GS_COLMASKONLYALPHA);
Set2DMode(true, 1, 1);
// set current vertex/fragment program
CCGVProgram_D3D *vpBlur=(CCGVProgram_D3D *)m_RP.m_VPBlur;
CCGPShader_D3D *fpBlur=(CCGPShader_D3D *)m_RP.m_RCBlur;
if (vpBlur && fpBlur)
{
vpBlur->mfSet(true, 0);
fpBlur->mfSet(true, 0);
// setup texture offsets, for texture neighboors sampling
float s1=1.0f/(float) nSizeX;
float t1=1.0f/(float) nSizeY;
float s_off=s1*0.5f;
float t_off=t1*0.5f;
float pfOffset0[]={ s1*0.5f, t1, 0.0f, 0.0f};
float pfOffset1[]={ -s1, t1*0.5f, 0.0f, 0.0f};
float pfOffset2[]={ -s1*0.5f, -t1, 0.0f, 0.0f};
float pfOffset3[]={ s1, -t1*0.5f, 0.0f, 0.0f};
EF_SelectTMU(0);
tpSrc->Set();
EF_SelectTMU(1);
tpSrc->Set();
EF_SelectTMU(2);
tpSrc->Set();
EF_SelectTMU(3);
tpSrc->Set();
vpBlur->mfParameter4f("Offset0", pfOffset0);
vpBlur->mfParameter4f("Offset1", pfOffset1);
vpBlur->mfParameter4f("Offset2", pfOffset2);
vpBlur->mfParameter4f("Offset3", pfOffset3);
// setup screen aligned quad
struct_VERTEX_FORMAT_P3F_TEX2F pScreenBlur[] =
{
Vec3(-s_off, -t_off, 0), 0, 0,
Vec3(-s_off, 1-t_off, 0), 0, 1,
Vec3(1-s_off, -t_off, 0), 1, 0,
Vec3(1-s_off, 1-t_off, 0), 1, 1,
};
int iBlurAmount = 1;
for(int iBlurPasses=1; iBlurPasses<=iBlurAmount; iBlurPasses++)
{
// set texture coordinates scale (needed for rectangular textures in gl ..)
float pfScale[]={ 1.0f, 1.0f, 1.0f, (float) iBlurPasses};
vpBlur->mfParameter4f("vTexCoordScale", pfScale);
// set current rendertarget
//pRenderer->m_pd3dDevice->SetRenderTarget( 0, pTexSurf);
// render screen aligned quad...
gRenDev->DrawTriStrip(&(CVertexBuffer (pScreenBlur,VERTEX_FORMAT_P3F_TEX2F)), 4);
}
vpBlur->mfSet(false, 0);
fpBlur->mfSet(false, 0);
EnableTMU(false);
EF_SelectTMU(2);
EnableTMU(false);
EF_SelectTMU(1);
EnableTMU(false);
EF_SelectTMU(0);
}
Set2DMode(false, 1, 1);
}
else
if (nType == 2)
{
EF_SetState(GS_NODEPTHTEST | GS_COLMASKONLYALPHA);
Set2DMode(true, 1, 1);
float s1=1.0f/(float) nSizeX;
float t1=1.0f/(float) nSizeY;
float s_off=s1*0.5f;
float t_off=t1*0.5f;
D3DXVECTOR4 avSampleOffsets[16];
D3DXVECTOR4 avSampleWeights[16];
// setup screen aligned quad
struct_VERTEX_FORMAT_P3F_TEX2F pScreenBlur[] =
{
Vec3(-s_off, -t_off, 0), 0, 0,
Vec3(-s_off, 1-t_off, 0), 0, 1,
Vec3(1-s_off, -t_off, 0), 1, 0,
Vec3(1-s_off, 1-t_off, 0), 1, 1,
};
RECT rectSrc;
GetTextureRect(tpSrc, &rectSrc);
InflateRect(&rectSrc, -1, -1);
RECT rectDest;
GetTextureRect(tpDst, &rectDest);
InflateRect(&rectDest, -1, -1);
CoordRect coords;
GetTextureCoords(tpSrc, &rectSrc, tpDst, &rectDest, &coords);
HRESULT hr = GetSampleOffsets_GaussBlur5x5Bilinear(tpSrc->m_Width, tpSrc->m_Height, avSampleOffsets, avSampleWeights, 1.0f);
if(tpSrc)
{
tpSrc->m_RefTex.m_MinFilter=D3DTEXF_LINEAR;
tpSrc->m_RefTex.m_MagFilter=D3DTEXF_LINEAR;
tpSrc->m_RefTex.bRepeats=false;
tpSrc->Set();
}
CCGPShader_D3D *fpGaussBlur5x5 = (CCGPShader_D3D *)PShaderForName(m_RP.m_PS_HDRGaussBlur5x5_Bilinear, "CGRC_HDR_GaussBlur5x5_Bilinear_PS20");
if (fpGaussBlur5x5)
{
fpGaussBlur5x5->mfSet(true);
SCGBind *bind = fpGaussBlur5x5->mfGetParameterBind("vSampleOffsets");
assert(bind);
fpGaussBlur5x5->mfParameter(bind, &avSampleOffsets[0].x, 9);
bind = fpGaussBlur5x5->mfGetParameterBind("vSampleWeights");
assert(bind);
fpGaussBlur5x5->mfParameter(bind, &avSampleWeights[0].x, 9);
// Draw a fullscreen quad to sample the RT
DrawTriStrip(&(CVertexBuffer (pScreenBlur,VERTEX_FORMAT_P3F_TEX2F)), 4);
fpGaussBlur5x5->mfSet(false);
}
Set2DMode(false, 1, 1);
}
else
if (nType >= 3)
{
if (!st->nTexId1)
st->nTexId1 = GenShadowTexture(st->nTexSize, false);
STexPicD3D *tpDst2 = (STexPicD3D *)m_TexMan->GetByID(st->nTexId1);
LPDIRECT3DTEXTURE9 pIRGBTarget2 = NULL;
IDirect3DSurface9 *pIRGBTargetSurf2 = NULL;
pIRGBTarget2 = (LPDIRECT3DTEXTURE9)tpDst2->m_RefTex.m_VidTex;
hReturn = pIRGBTarget2->GetSurfaceLevel(0, &pIRGBTargetSurf2);
hReturn = m_pd3dDevice->SetRenderTarget(0, pIRGBTargetSurf2);
SAFE_RELEASE(pIRGBTargetSurf2);
Set2DMode(true, 1, 1);
EF_SetState(GS_NODEPTHTEST | GS_COLMASKONLYALPHA);
// setup screen aligned quad
struct_VERTEX_FORMAT_P3F_TEX2F pScreenBlur[] =
{
Vec3(0, 0, 0), 0, 0,
Vec3(0, 1, 0), 0, 1,
Vec3(1, 0, 0), 1, 0,
Vec3(1, 1, 0), 1, 1,
};
if(tpSrc)
{
tpSrc->m_RefTex.m_MinFilter=D3DTEXF_LINEAR;
tpSrc->m_RefTex.m_MagFilter=D3DTEXF_LINEAR;
tpSrc->m_RefTex.bRepeats=false;
tpSrc->Set();
}
CCGPShader_D3D *fpGaussSep = (CCGPShader_D3D *)PShaderForName(m_RP.m_PS_GaussBlurSep, "CGRCBlurSep");
CCGVProgram_D3D *vpGaussSep = (CCGVProgram_D3D *)VShaderForName(m_RP.m_VS_GaussBlurSep, "CGVProgBlurSep");
if (fpGaussSep && vpGaussSep)
{
static float sW[8] = {0.2537f, 0.2185f, 0.0821f, 0.0461f, 0.0262f, 0.0162f, 0.0102f, 0.0052f};
int i;
fpGaussSep->mfSet(true);
vpGaussSep->mfSet(true);
vec4_t v;
v[0] = 1.0f/(float)nSizeX;
v[1] = 1.0f/(float)nSizeY;
v[2] = 0;
v[3] = 0;
SCGBind *bindOffs = vpGaussSep->mfGetParameterBind("PixelOffset");
assert(bindOffs);
vpGaussSep->mfParameter(bindOffs, v, 1);
// X Blur
v[0] = 1.0f/(float)nSizeX;
v[1] = 0;
bindOffs = fpGaussSep->mfGetParameterBind("BlurOffset");
assert(bindOffs);
fpGaussSep->mfParameter(bindOffs, v, 1);
vec4_t vWeight[8];
for (i=0; i<8; i++)
{
vWeight[i][0] = sW[i];
vWeight[i][1] = sW[i];
vWeight[i][2] = sW[i];
vWeight[i][3] = sW[i];
}
SCGBind *bindW = fpGaussSep->mfGetParameterBind("vPixelWeights");
assert(bindW);
fpGaussSep->mfParameter(bindW, &vWeight[0][0], 8);
// Draw a fullscreen quad to sample the RT
DrawTriStrip(&(CVertexBuffer (pScreenBlur,VERTEX_FORMAT_P3F_TEX2F)), 4);
// Y Blur
v[0] = 0;
v[1] = 1.0f/(float)nSizeY;
fpGaussSep->mfParameter(bindOffs, v, 1);
hReturn = m_pd3dDevice->SetRenderTarget(0, pIRGBTargetSurf);
SAFE_RELEASE(pIRGBTargetSurf);
tpDst2->Set();
// Draw a fullscreen quad to sample the RT
DrawTriStrip(&(CVertexBuffer (pScreenBlur,VERTEX_FORMAT_P3F_TEX2F)), 4);
fpGaussSep->mfSet(false);
vpGaussSep->mfSet(false);
}
Set2DMode(false, 1, 1);
}
SAFE_RELEASE(pIRGBTargetSurf);
}
unsigned int CD3D9Renderer::GenShadowTexture(int nSize, bool bProjected)
{
byte *data = new byte[nSize*nSize*4];
char name[128];
sprintf(name, "$AutoShadowMaps_%d", m_TexGenID++);
int flags = FT_NOMIPS | FT_CLAMP | FT_NOSTREAM | FT_HASALPHA;
if (bProjected)
flags |= FT_PROJECTED;
int flags2 = FT2_RENDERTARGET | FT2_NODXT;
ETEX_Format eTF;
if ((m_Features & RFT_DEPTHMAPS) && bProjected)
eTF = eTF_DEPTH;
else
eTF = eTF_8888;
STexPic *tp = m_TexMan->CreateTexture(name, nSize, nSize, 1, flags, flags2, data, eTT_Base, -1.0f, -1.0f, 0, NULL, 0, eTF);
STexPicD3D *t = (STexPicD3D *)tp;
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
delete [] data;
if (!t)
return 0;
pID3DTexture = (LPDIRECT3DTEXTURE9)t->m_RefTex.m_VidTex;
if (!pID3DTexture)
return 0;
return t->m_Bind;
}
// draw grid and project depth map on it
/*void CD3D9Renderer::DrawShadowGrid(const Vec3d & pos, const Vec3d & Scale, ShadowMapFrustum*lf, bool translate_projection, float alpha, IndexedVertexBuffer* pVertexBuffer, float anim_angle)
{
} */
// Make 8-bit identity texture that maps (s)=(z) to [0,255]/255.
int CD3D9Renderer::MakeShadowIdentityTexture()
{
return 0;
}
void CD3D9Renderer::OnEntityDeleted(IEntityRender * pEntityRender)
{ // remove references to the entity
for(int i=0; i<MAX_DYNAMIC_SHADOW_MAPS_COUNT; i++)
{
ShadowMapTexInfo * pInf = &m_ShadowTexIDBuffer[i];
if(pInf->pOwner == pEntityRender)
pInf->pOwner = NULL;
}
}
void DrawText(ISystem * pSystem, int x, int y, const char * format, ...)
{
char buffer[512];
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
ICryFont *pCryFont = pSystem->GetICryFont();
if (!pCryFont)
return;
IFFont *pFont = pCryFont->GetFont("console");
if (!pFont)
return;
pFont->UseRealPixels(false);
pFont->SetSameSize(true);
pFont->SetCharWidthScale(1);
pFont->SetSize(vector2f(12, 12));
pFont->SetColor(color4f(1,1,1,1));
pFont->SetCharWidthScale(.5f);
pFont->DrawString( (float)x/*-pFont->GetCharWidth() * strlen(buffer) * pFont->GetCharWidthScale(*)*/, (float)y, buffer );
}
void CD3D9Renderer::DrawAllShadowsOnTheScreen()
{
float width=800;
float height=600;
Set2DMode(true, (int)width, (int)height);
float fArrDim = max(4, sqrt(float(MAX_DYNAMIC_SHADOW_MAPS_COUNT)));
float fPicDimX = width/fArrDim;
float fPicDimY = height/fArrDim;
int nShadowId=0;
for(float x=0; nShadowId<MAX_DYNAMIC_SHADOW_MAPS_COUNT && x<width-10; x+=fPicDimX)
for(float y=0; nShadowId<MAX_DYNAMIC_SHADOW_MAPS_COUNT && y<height-10; y+=fPicDimY)
{
ShadowMapTexInfo * pInf = &m_ShadowTexIDBuffer[nShadowId++];
if(pInf->nTexId0 && (pInf->pOwner || pInf->pOwnerGroup))
{
STexPic *tp = (STexPic *)EF_GetTextureByID(pInf->nTexId0);
if (tp)
{
byte bSaveProj = tp->m_RefTex.bProjected;
tp->m_RefTex.bProjected = false;
SetState( GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST );
Draw2dImage(x, y, fPicDimX, fPicDimY, pInf->nTexId0, 0,0,1,1,180);
const char * pName = pInf->pOwner ? pInf->pOwner->GetName() : pInf->pOwnerGroup->GetFileName();
int nLen = strlen(pName);
DrawText(iSystem, (int)(x/width*800.f), (int)(y/height*600.f), "%8s-%d", pName + max(0, nLen - 12), pInf->nLastFrameID&7);
tp->m_RefTex.bProjected = bSaveProj;
}
}
}
Set2DMode(false, m_width, m_height);
}
void CD3D9Renderer::PrepareDepthMap(ShadowMapFrustum * lof, bool make_new_tid)
{
PROFILE_FRAME(Prep_PrepareDepthMap);
if(!lof || !lof->pLs)
return;
static int nCurTexIdSlot = 0;
//lof->bUpdateRequested = true;
if (lof->nResetID != m_nFrameReset)
{
lof->nResetID = m_nFrameReset;
lof->bUpdateRequested = true;
}
lof->nTexSize = max(lof->nTexSize, 32);
if(lof->nTexIdSlot>=0)
{
if(m_ShadowTexIDBuffer[lof->nTexIdSlot].pOwner == lof->pOwner)
{
char * pName = 0;
if(lof->pOwner)
pName = (char*)lof->pOwner->GetName();
if(m_ShadowTexIDBuffer[lof->nTexIdSlot].pOwnerGroup == lof->pOwnerGroup)
if(m_ShadowTexIDBuffer[lof->nTexIdSlot].dwFlags == lof->dwFlags)
if(lof->depth_tex_id && !lof->bUpdateRequested)
{
m_ShadowTexIDBuffer[lof->nTexIdSlot].nLastFrameID = GetFrameID();
return;
}
}
}
int nShadowTexSize = lof->nTexSize;
lof->bUpdateRequested = false;
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Render objects into frame and Z buffers
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// remember fog value
EF_PushFog();
EnableFog(false);
EF_PushMatrix();
m_matProj->Push();
// normalize size
//while(nShadowTexSize>m_height || nShadowTexSize>m_width)
// nShadowTexSize/=2;
if (m_LogFile)
Logv(SRendItem::m_RecurseLevel, " Really generating %dx%d shadow map for %s, [%s] \n",
nShadowTexSize, nShadowTexSize,
lof->pOwner ? lof->pOwner->GetName() : "NoOwner",
lof->pOwnerGroup ? lof->pOwnerGroup->GetFileName() : "NoGroup");
// setup matrices
int vX, vY, vWidth, vHeight;
gRenDev->GetViewport(&vX, &vY, &vWidth, &vHeight);
gRenDev->SetViewport(0, 0, nShadowTexSize, nShadowTexSize);
Matrix44 camMatr = m_CameraMatrix;
D3DXMATRIX *m = m_matProj->GetTop();
if (m_Features & RFT_DEPTHMAPS)
D3DXMatrixPerspectiveFovRH(m, lof->FOV*(gf_PI/180.0f), lof->ProjRatio, lof->min_dist, lof->max_dist+50);
else
D3DXMatrixPerspectiveFovRH(m, lof->FOV*(gf_PI/180.0f), lof->ProjRatio, lof->min_dist, lof->max_dist);
//makeProjectionMatrix(lof->FOV, 1, lof->min_dist, lof->max_dist, (float *)m);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m);
m_bInvertedMatrix = false;
memcpy(lof->debugLightFrustumMatrix,m,sizeof(lof->debugLightFrustumMatrix));
m = m_matView->GetTop();
D3DXVECTOR3 Eye = D3DXVECTOR3(lof->pLs->vSrcPos.x, lof->pLs->vSrcPos.y, lof->pLs->vSrcPos.z);
D3DXVECTOR3 At = D3DXVECTOR3(lof->target.x, lof->target.y, lof->target.z);
D3DXVECTOR3 Up = D3DXVECTOR3(0,0,1);
D3DXMatrixLookAtRH(m, &Eye, &At, &Up);
m_pd3dDevice->SetTransform(D3DTS_VIEW, m);
memcpy(lof->debugLightViewMatrix, m, sizeof(lof->debugLightViewMatrix));
//EF_SetCameraInfo();
if (!m_SceneRecurseCount)
m_pd3dDevice->BeginScene();
m_SceneRecurseCount++;
if(make_new_tid)
{ // new id for static objects
assert (!lof->depth_tex_id);
lof->depth_tex_id = GenShadowTexture(nShadowTexSize, true);
assert(lof->depth_tex_id<14000);
}
else
{
// try to reuse slot if it was not modified
if( lof->nTexIdSlot>=0 &&
m_ShadowTexIDBuffer[lof->nTexIdSlot].nTexId0 == lof->depth_tex_id &&
m_ShadowTexIDBuffer[lof->nTexIdSlot].nTexSize == nShadowTexSize &&
m_ShadowTexIDBuffer[lof->nTexIdSlot].pOwner == lof->pOwner &&
m_ShadowTexIDBuffer[lof->nTexIdSlot].pOwnerGroup == lof->pOwnerGroup &&
m_ShadowTexIDBuffer[lof->nTexIdSlot].dwFlags == lof->dwFlags)
{
nCurTexIdSlot = lof->nTexIdSlot;
}
else
{ // find oldest slot
int nOldestSlot = -1;
int nOldestFrameId = GetFrameID();
for(int i=0; i<MAX_DYNAMIC_SHADOW_MAPS_COUNT; i++)
{
if(m_ShadowTexIDBuffer[i].nLastFrameID < nOldestFrameId && nShadowTexSize == m_ShadowTexIDBuffer[i].nTexSize)
{
nOldestFrameId = m_ShadowTexIDBuffer[i].nLastFrameID;
nOldestSlot = i;
}
}
if(nOldestSlot<0)
nCurTexIdSlot++;
else
nCurTexIdSlot=nOldestSlot;
}
if(nCurTexIdSlot>=MAX_DYNAMIC_SHADOW_MAPS_COUNT)
nCurTexIdSlot=0;
if(!m_ShadowTexIDBuffer[nCurTexIdSlot].nTexId0)
{
//assert(false);
m_ShadowTexIDBuffer[nCurTexIdSlot].nTexId0 = GenShadowTexture(nShadowTexSize, true);
assert(m_ShadowTexIDBuffer[nCurTexIdSlot].nTexId0<14000);
//assert(m_TexMan->GetByID(m_ShadowTexIDBuffer[nCurTexIdSlot].nTexId));
make_new_tid = true;
}
lof->nTexIdSlot = nCurTexIdSlot;
STexPic *tpOld = m_TexMan->GetByID(m_ShadowTexIDBuffer[nCurTexIdSlot].nTexId0);
assert(tpOld);
if (!tpOld || tpOld->m_Width != nShadowTexSize)
{
//assert (false);
//ResetToDefault();
if(tpOld)
tpOld->Release(0);
m_ShadowTexIDBuffer[nCurTexIdSlot].nTexId0 = lof->depth_tex_id = GenShadowTexture(nShadowTexSize, true);
}
else
lof->depth_tex_id = m_ShadowTexIDBuffer[nCurTexIdSlot].nTexId0;
m_ShadowTexIDBuffer[nCurTexIdSlot].pOwner = lof->pOwner;
m_ShadowTexIDBuffer[nCurTexIdSlot].pOwnerGroup = lof->pOwnerGroup;
m_ShadowTexIDBuffer[nCurTexIdSlot].dwFlags = lof->dwFlags;
m_ShadowTexIDBuffer[nCurTexIdSlot].nLastFrameID = GetFrameID();
m_ShadowTexIDBuffer[nCurTexIdSlot].nTexSize = nShadowTexSize;
}
assert(m_ShadowTexIDBuffer[0].nTexId0 ? m_TexMan->GetByID(m_ShadowTexIDBuffer[0].nTexId0)!=NULL : 1);
// assert(m_ShadowTexIDBuffer[1].nTexId ? m_TexMan->GetByID(m_ShadowTexIDBuffer[1].nTexId)!=NULL : 1);
ShadowMapTexInfo *st = NULL;
HRESULT hReturn;
IDirect3DSurface9 *pIRGBTargetSurf = NULL;
IDirect3DSurface9 *pIZBufferSurf = NULL;
LPDIRECT3DTEXTURE9 pID3DTexture = NULL;
LPDIRECT3DTEXTURE9 pIRGBTarget = NULL;
// Create color buffer render target. We aren't actually going to use it for anything,
// but D3D required one as rendertarget
bool bStatus = false;
if (m_Features & RFT_DEPTHMAPS)
{
bStatus = true;
// Set render target
STexPicD3D *tp = (STexPicD3D *)m_TexMan->GetByID(lof->depth_tex_id);
assert(tp->m_ETF == eTF_DEPTH);
int i;
for (i=0; i<m_TempShadowTextures.Num(); i++)
{
st = &m_TempShadowTextures[i];
if (st->nTexSize == nShadowTexSize)
break;
}
if (i == m_TempShadowTextures.Num())
{
ShadowMapTexInfo smt;
smt.nTexId0 = 0;
smt.nTexSize = nShadowTexSize;
m_TempShadowTextures.AddElem(smt);
}
st = &m_TempShadowTextures[i];
if (!st->nTexId0)
st->nTexId0 = GenShadowTexture(nShadowTexSize, false);
STexPicD3D *tpRGB = (STexPicD3D *)m_TexMan->GetByID(st->nTexId0);
if (tp)
{
pID3DTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex;
if (pID3DTexture)
hReturn = pID3DTexture->GetSurfaceLevel(0, &pIZBufferSurf);
}
//hReturn = m_pd3dDevice->CreateTexture(nShadowTexSize, nShadowTexSize, 1, D3DUSAGE_RENDERTARGET, m_d3dsdBackBuffer.Format, D3DPOOL_DEFAULT, &pIRGBTarget, NULL);
if (tpRGB)
{
pIRGBTarget = (LPDIRECT3DTEXTURE9)tpRGB->m_RefTex.m_VidTex;
if (pIRGBTarget)
hReturn = pIRGBTarget->GetSurfaceLevel(0, &pIRGBTargetSurf);
}
hReturn = m_pd3dDevice->SetRenderTarget(0, pIRGBTargetSurf);
hReturn = m_pd3dDevice->SetDepthStencilSurface(pIZBufferSurf);
// Disable color writes
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
}
else
{
bStatus = true;
// Set render target
STexPicD3D *tp = (STexPicD3D *)m_TexMan->GetByID(lof->depth_tex_id);
//assert(tp->m_ETF == eTF_DEPTH);
if (tp)
pID3DTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex;
if (CV_r_shadowblur)
{
int i;
for (i=0; i<m_TempShadowTextures.Num(); i++)
{
st = &m_TempShadowTextures[i];
if (st->nTexSize == nShadowTexSize)
break;
}
if (i == m_TempShadowTextures.Num())
{
ShadowMapTexInfo smt;
smt.nTexId0 = 0;
smt.nTexSize = nShadowTexSize;
m_TempShadowTextures.AddElem(smt);
}
st = &m_TempShadowTextures[i];
if (!st->nTexId0)
st->nTexId0 = GenShadowTexture(nShadowTexSize, false);
tp = (STexPicD3D *)m_TexMan->GetByID(st->nTexId0);
if (tp)
pID3DTexture = (LPDIRECT3DTEXTURE9)tp->m_RefTex.m_VidTex;
}
if (pID3DTexture)
{
hReturn = pID3DTexture->GetSurfaceLevel(0, &pIRGBTargetSurf);
hReturn = m_pd3dDevice->SetRenderTarget(0, pIRGBTargetSurf);
hReturn = m_pd3dDevice->SetDepthStencilSurface(m_pTempZBuffer);
}
}
int ClipPlanes = m_RP.m_ClipPlaneEnabled;
SPlane clP = m_RP.m_CurClipPlane;
int nPersFlags = m_RP.m_PersFlags;
m_RP.m_PersFlags &= ~RBPF_HDR;
if (bStatus)
{
// clear frame buffer
CFColor col;
if (!(m_Features & RFT_DEPTHMAPS) && (m_Features & RFT_SHADOWMAP_SELFSHADOW))
{
col = CFColor(1,0.879f,0,0);
EF_ClearBuffers(true, false, &col[0]);
}
else
{
col = CFColor(0,0,0,0);
EF_ClearBuffers(true, false, &col[0]);
}
RECT scRect;
scRect.left = 3;
scRect.right = nShadowTexSize-3;
scRect.top = 3;
scRect.bottom = nShadowTexSize-3;
m_pd3dDevice->SetScissorRect(&scRect);
m_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
IShader * pStateShader = EF_LoadShader("StateNoCull", eSH_World, EF_SYSTEM);
// draw static objects (not entities)
if(lof->pModelsList && lof->pModelsList->Count())
{
if (!(m_Features & RFT_DEPTHMAPS | RFT_SHADOWMAP_SELFSHADOW))
{
// cut underground geometry
float plane[] = {0,0,1,0};
gRenDev->SetClipPlane(0,plane);
}
EF_StartEf();
for(int m=0; m<lof->pModelsList->Count(); m++)
{
SRendParams rParms;
rParms.pStateShader = pStateShader;
if (m_Features & RFT_DEPTHMAPS)
rParms.nShaderTemplate = EFT_WHITE;
else
rParms.nShaderTemplate = EFT_WHITESHADOW;
// set pos relative to entity 0
if(lof->pEntityList && lof->pEntityList->Count())
rParms.vPos -= (*lof->pEntityList)[0]->GetPos();
rParms.dwFObjFlags |= FOB_TRANS_MASK;
rParms.dwFObjFlags |= FOB_RENDER_INTO_SHADOWMAP;
rParms.fBending = lof->m_fBending;
(*lof->pModelsList)[m]->Render(rParms,Vec3(zero),0);
}
EF_EndEf3D(true);
}
// draw entities
EF_StartEf();
for(int m=0; lof->pEntityList && m_RP.m_pCurObject && m<lof->pEntityList->Count(); m++)
{
IEntityRender * pEnt = (*lof->pEntityList)[m];
const char *name = pEnt->GetName();
Vec3d vOffSetDir = -GetNormalized( lof->pLs->vSrcPos )*(0.1f+0.035f*(256.f/nShadowTexSize));
IEntityRender * pEnt0 = (*lof->pEntityList)[0];
SRendParams rParams;
if (m_Features & RFT_DEPTHMAPS)
rParams.nShaderTemplate = EFT_WHITE;
else
rParams.nShaderTemplate = EFT_WHITESHADOW;
rParams.pStateShader = pStateShader;
rParams.vPos = vOffSetDir*lof->fOffsetScale + (pEnt->GetPos() - lof->pOwner->GetPos());
rParams.dwFObjFlags |= FOB_RENDER_INTO_SHADOWMAP;
rParams.dwFObjFlags |= FOB_TRANS_MASK;
pEnt->DrawEntity(rParams);
}
EF_EndEf3D(true);
//memcpy(lof->debugLightViewMatrix, &CCGVProgram_D3D::m_CurParams[0][0], 4*4*sizeof(float));
if (m_Features & RFT_DEPTHMAPS)
{
// Enable color writes
m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0xf);
}
// Blur 2D texture
if (st && !(m_Features & RFT_DEPTHMAPS))
{
SAFE_RELEASE(pIRGBTargetSurf);
int BlurType = CV_r_shadowblur-1;
if (CV_r_shadowblur > 2)
{
if (CRenderer::CV_r_nops20)
BlurType = 1;
}
BlurImage(nShadowTexSize, nShadowTexSize, BlurType, st, lof->depth_tex_id);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Now make texture from frame buffer
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (CD3D9Renderer::CV_d3d9_savedepthmaps)
{
if (m_Features & RFT_DEPTHMAPS)
{
m_matProj->Push();
D3DXMatrixOrthoRH( m_matProj->GetTop(), (float)nShadowTexSize, (float)nShadowTexSize, -20.0f, 0.0f);
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m_matProj->GetTop());
EF_PushMatrix();
m_matView->LoadIdentity();
m_pd3dDevice->SetTransform(D3DTS_VIEW, m_matView->GetTop());
m_TexMan->m_Text_White->Set();
EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
SetCullMode(R_CULL_NONE);
EF_SetState(GS_NODEPTHTEST);
DrawQuad(0, 0, (float)nShadowTexSize, (float)nShadowTexSize, CFColor(0.0f));
EF_SetState(0);
DrawQuad(0, 0, (float)nShadowTexSize, (float)nShadowTexSize, CFColor(1.0f));
LPDIRECT3DTEXTURE9 pID3DSysTexture;
LPDIRECT3DSURFACE9 pSysSurf;
D3DLOCKED_RECT d3dlrSys;
hReturn = D3DXCreateTexture(m_pd3dDevice, nShadowTexSize, nShadowTexSize, 1, 0, m_d3dsdBackBuffer.Format, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
hReturn = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
hReturn = m_pd3dDevice->GetRenderTargetData(pIRGBTargetSurf, pSysSurf);
hReturn = pID3DSysTexture->LockRect(0, &d3dlrSys, NULL, 0);
byte *pic = new byte [nShadowTexSize * nShadowTexSize * 4];
// Copy data to the texture
cryMemcpy(pic, d3dlrSys.pBits, nShadowTexSize*nShadowTexSize*4);
char buff[128];
sprintf(buff, "ShadowMap%02d.tga", nCurTexIdSlot);
::WriteTGA(pic,nShadowTexSize,nShadowTexSize,buff,32);
delete [] pic;
hReturn = pID3DSysTexture->UnlockRect(0);
SAFE_RELEASE(pSysSurf);
SAFE_RELEASE(pID3DSysTexture);
EF_PopMatrix();
m_matProj->Pop();
}
else
{
LPDIRECT3DTEXTURE9 pID3DSysTexture;
LPDIRECT3DSURFACE9 pSysSurf;
D3DLOCKED_RECT d3dlrSys;
//hReturn = D3DXCreateTexture(m_pd3dDevice, nShadowTexSize, nShadowTexSize, 1, 0, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
hReturn = D3DXCreateTexture(m_pd3dDevice, nShadowTexSize, nShadowTexSize, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pID3DSysTexture );
hReturn = pID3DSysTexture->GetSurfaceLevel(0, &pSysSurf);
hReturn = m_pd3dDevice->GetRenderTargetData(pIRGBTargetSurf, pSysSurf);
hReturn = pID3DSysTexture->LockRect(0, &d3dlrSys, NULL, 0);
byte *pic = new byte [nShadowTexSize*nShadowTexSize*4];
byte *ds = (byte *)d3dlrSys.pBits;
memcpy(pic, ds, nShadowTexSize*nShadowTexSize*4);
/*for (int i=0; i<nShadowTexSize; i++)
{
int ni0 = (i*nShadowTexSize)*4;
int ni1 = i*d3dlrSys.Pitch;
ushort *ds1 = (ushort *)&ds[ni1];
uint *pic1 = (uint *)&pic[ni0];
for (int j=0; j<nShadowTexSize; j++)
{
uint argb = *ds1++;
*pic1++ = (((argb << 8)*4) & 0xff0000) |
(((argb << 5)*5) & 0xff00) |
(((argb << 3)*4) & 0x00FF);
}
}*/
hReturn = pID3DSysTexture->UnlockRect(0);
char buff[128];
sprintf(buff, "ShadowMap%02d.tga", nCurTexIdSlot);
::WriteTGA(pic,nShadowTexSize,nShadowTexSize,buff,32);
delete [] pic;
SAFE_RELEASE(pSysSurf);
SAFE_RELEASE(pID3DSysTexture);
}
}
}
if (ClipPlanes)
EF_SetClipPlane(true, &clP.m_Normal.x, false);
m_RP.m_PersFlags = nPersFlags;
if (m_Features & RFT_DEPTHMAPS)
{
hReturn = m_pd3dDevice->SetDepthStencilSurface(m_pCurZBuffer);
if (m_RP.m_PersFlags & RBPF_HDR)
hReturn = m_pd3dDevice->SetRenderTarget(0, m_pHDRTargetSurf);
else
hReturn = m_pd3dDevice->SetRenderTarget(0, m_pCurBackBuffer);
SAFE_RELEASE(pIRGBTargetSurf);
//SAFE_RELEASE(pIRGBTarget);
SAFE_RELEASE(pIZBufferSurf);
}
else
{
if (m_RP.m_PersFlags & RBPF_HDR)
hReturn = m_pd3dDevice->SetRenderTarget(0, m_pHDRTargetSurf);
else
hReturn = m_pd3dDevice->SetRenderTarget(0, m_pCurBackBuffer);
hReturn = m_pd3dDevice->SetDepthStencilSurface(m_pCurZBuffer);
SAFE_RELEASE(pIRGBTargetSurf);
}
EF_PopMatrix();
m_matProj->Pop();
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, m_matProj->GetTop());
m_CameraMatrix = camMatr;
m_matView->LoadMatrix((D3DXMATRIX *)camMatr.GetData());
EF_SetCameraInfo();
m_bInvertedMatrix = false;
SetViewport(vX, vY, vWidth, vHeight);
m_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
m_sPrevX = 1;
m_sPrevY = 1;
m_sPrevWdt = nShadowTexSize-1;
m_sPrevHgt = nShadowTexSize-1;
EF_PopFog();
m_SceneRecurseCount--;
if (!m_SceneRecurseCount)
m_pd3dDevice->EndScene();
assert(m_ShadowTexIDBuffer[0].nTexId0 ? m_TexMan->GetByID(m_ShadowTexIDBuffer[0].nTexId0)!=NULL : 1);
if(lof->pPenumbra && lof->pPenumbra->bUpdateRequested)
PrepareDepthMap(lof->pPenumbra, make_new_tid);
}
void MakePenumbraTextureFromDepthMap(byte * pDepthMapIn, int nSize, byte * pPenumbraMapOut)
{
cryMemcpy(pPenumbraMapOut,pDepthMapIn,nSize*nSize);
BlurImage8(pPenumbraMapOut, nSize, 3);
#define DATA_TMP(_x,_y) (pTemp[(_x)+nSize*(_y)])
#define DATA(_x,_y) (pPenumbraMapOut[(_x)+nSize*(_y)])
{ // substract
for(int x=0; x<nSize; x++)
for(int y=0; y<nSize; y++)
{
float fVal = (float)DATA(x,y) - (float)pDepthMapIn[x+nSize*y];
fVal = (fVal*2.f) + 127.f;
DATA(x,y) = uchar( max(min(fVal,255),0) );
}
}
cryMemcpy(pDepthMapIn,pPenumbraMapOut,nSize*nSize);
{ // per fragment normalization
int nRange = 1;
for(int X=nRange; X<nSize-nRange; X++)
for(int Y=nRange; Y<nSize-nRange; Y++)
{
// DATA(X,Y) = DATA(X,Y)>4 ? 255 : 0;
}
}
/*
{ // per fragment normalization
int nRange = 8;
for(int X=nRange; X<nSize-nRange-1; X++)
for(int Y=nRange; Y<nSize-nRange-1; Y++)
{
float fMax = 0;
for(int x=X-nRange; x<=X+nRange; x++)
for(int y=Y-nRange; y<=Y+nRange; y++)
{
if(fMax < pDepthMapIn[x+nSize*y])
fMax = pDepthMapIn[x+nSize*y];
}
if(fMax)
{
float fValue = (float)pDepthMapIn[X+nSize*Y];
float fNewValue = (fValue/fMax)*255.f;
DATA(X,Y) = uchar( max(min(fNewValue,255),0) );
}
else
{
DATA(X,Y) = 0;
}
}
}*/
#undef DATA
#undef DATA_IN
// BlurImage8(pPenumbraMapOut, nSize, 1);
}
void CD3D9Renderer::SetupShadowOnlyPass(int Num, ShadowMapFrustum * pFrustum, Vec3d * vShadowTrans, const float fShadowScale, Vec3d vObjTrans, float fObjScale, const Vec3d vObjAngles, Matrix44 * pObjMat)
{
if(!pFrustum)
return;
D3DXMATRIX lightFrustumMatrix;
D3DXMATRIX lightViewMatrix;
if(vShadowTrans)
{ // make tmp matrix for this obj position if shadow frustum is not translated (translate original mats)
//float fDist = (pFrustum->min_dist + pFrustum->max_dist)*0.5f;
//float fDiam = (pFrustum->max_dist - pFrustum->min_dist);//*fShadowScale;
//D3DXMatrixPerspectiveFovRH(&lightFrustumMatrix, pFrustum->FOV*fShadowScale*(gf_PI/180.0f), 1, pFrustum->min_dist, pFrustum->max_dist+10);
if (m_Features & RFT_DEPTHMAPS)
makeProjectionMatrix(pFrustum->FOV*fShadowScale, pFrustum->ProjRatio, pFrustum->min_dist, pFrustum->max_dist+50, lightFrustumMatrix);
else
D3DXMatrixPerspectiveFovRH(&lightFrustumMatrix, pFrustum->FOV*fShadowScale*(gf_PI/180.0f), pFrustum->ProjRatio, pFrustum->min_dist, pFrustum->max_dist);
Vec3d mv_trans = *vShadowTrans;// - vObjTrans;
D3DXMATRIX mat;
D3DXVECTOR3 Eye = D3DXVECTOR3(
pFrustum->pLs->vSrcPos.x+mv_trans.x,
pFrustum->pLs->vSrcPos.y+mv_trans.y,
pFrustum->pLs->vSrcPos.z+mv_trans.z);
D3DXVECTOR3 At = D3DXVECTOR3(
fShadowScale*pFrustum->target.x+mv_trans.x,
fShadowScale*pFrustum->target.y+mv_trans.y,
fShadowScale*pFrustum->target.z+mv_trans.z);
D3DXVECTOR3 Up = D3DXVECTOR3(0,0,1);
D3DXMatrixLookAtRH(&mat, &Eye, &At, &Up);
if(pObjMat)
mathMatrixMultiply(lightViewMatrix, mat, pObjMat->GetData(), g_CpuFlags);
else
{
mathRotateZ(mat, vObjAngles.z, g_CpuFlags);
mathRotateY(mat, vObjAngles.y, g_CpuFlags);
mathRotateX(mat, vObjAngles.x, g_CpuFlags);
mathScale(mat, Vec3d(fObjScale,fObjScale,fObjScale), g_CpuFlags);
memcpy(lightViewMatrix, mat, sizeof(float)*16);
}
}
CD3D9TexMan::BindNULL(1);
ConfigShadowTexgen(Num, 0, pFrustum, lightFrustumMatrix, lightViewMatrix, pFrustum->debugLightViewMatrix);
}
// setup projection texgen
void CD3D9Renderer::ConfigShadowTexgen(int Num, int rangeMap, ShadowMapFrustum * pFrustum, float * pLightFrustumMatrix, float * pLightViewMatrix, float *ModelVPMatrix)
{
float m1[16], m2[16];
float *mtexSc;
if (rangeMap)
{
int to_map_8bit = MakeShadowIdentityTexture();
float RSmatrix[16] =
{
0, 0, 0, 0,
0, 0, 0, 0,
0.5f, 128, 0, 0,
0.5f, 128, 0, 1.0f
};
if (Num >= 0)
{
m_RP.m_pRE->m_CustomTexBind[Num] = to_map_8bit;
gRenDev->m_TexMan->SetTexture(to_map_8bit, eTT_Base);
}
else
{
//glBindTexture(GL_TEXTURE_1D, to_map_8bit);
//glEnable(GL_TEXTURE_1D);
//glDisable(GL_TEXTURE_2D);
}
memcpy(m1,RSmatrix,sizeof(m1));
}
else
{
if ((m_Features & RFT_DEPTHMAPS))
{
// Compensate for D3D's texel adressing, we need 1:1 texel - pixel matching
float fOffsetX = 0.5f + (0.5f / (float) pFrustum->nTexSize);
float fOffsetY = 0.5f + (0.5f / (float) pFrustum->nTexSize);
float Smatrix[16] =
{
0.5f, 0, 0, 0,
0, -0.5f, 0, 0,
0, 0, 0.5f, 0,
fOffsetX, fOffsetY, 0.5f, 1.0f
};
mtexSc = Smatrix;
}
else
{
static float Smatrix[16] =
{
0.5f, 0, 0, 0,
0, -0.5f, 0, 0,
0, 0, 0, 0,
0.5f, 0.5f, 1.0f, 1.0f
};
mtexSc = Smatrix;
}
}
mathMatrixMultiply(m2, pLightFrustumMatrix, pLightViewMatrix, g_CpuFlags);
mathMatrixMultiply(m1, mtexSc, m2, g_CpuFlags);
{
Matrix44 *mt = &gRenDev->m_cEF.m_TempMatrices[Num][0];
float *pf = mt->GetData();
//memcpy(pf, m1, 4*4*4);
mathMatrixTranspose(pf, m1, g_CpuFlags);
}
if ((m_Features & RFT_SHADOWMAP_SELFSHADOW) && !(m_Features & RFT_DEPTHMAPS))
{
Matrix44 *mt = &gRenDev->m_cEF.m_TempMatrices[Num][7];
float *pf = mt->GetData();
mathMatrixTranspose(pf, m2, g_CpuFlags);
}
if (Num >= 0)
{
if(pFrustum->depth_tex_id<=0)
Warning( 0,0,"Warning: CD3D9Renderer::ConfigShadowTexgen: pFrustum->depth_tex_id not set");
else
{
if (m_RP.m_pRE)
{
m_RP.m_pRE->m_CustomTexBind[Num] = pFrustum->depth_tex_id;
m_RP.m_pRE->m_Color[Num] = pFrustum->fAlpha;
}
else
{
m_RP.m_RECustomTexBind[Num] = pFrustum->depth_tex_id;
m_RP.m_REColor[Num] = pFrustum->fAlpha;
}
}
if (m_RP.m_pCurLight)
{
float fRadius;
if (m_RP.m_ObjFlags & FOB_TRANS_MASK)
{
float fLen = m_RP.m_pCurObject->m_Matrix(0,0)*m_RP.m_pCurObject->m_Matrix(0,0) + m_RP.m_pCurObject->m_Matrix(0,1)*m_RP.m_pCurObject->m_Matrix(0,1) + m_RP.m_pCurObject->m_Matrix(0,2)*m_RP.m_pCurObject->m_Matrix(0,2);
unsigned int *n1 = (unsigned int *)&fLen;
unsigned int n = 0x5f3759df - (*n1 >> 1);
float *n2 = (float *)&n;
float fISqrt = (1.5f - (fLen * 0.5f) * *n2 * *n2) * *n2;
fRadius = m_RP.m_pCurLight->m_fRadius * fISqrt;
}
else
fRadius = m_RP.m_pCurLight->m_fRadius;
m_RP.m_REColor[3] = 1.0f / fRadius;
if (m_RP.m_pRE)
m_RP.m_pRE->m_Color[3] = m_RP.m_REColor[3];
}
else
{
m_RP.m_REColor[3] = 1.0f / 10000.0f;
if (m_RP.m_pRE)
m_RP.m_pRE->m_Color[3] = m_RP.m_REColor[3];
}
STexPic *tp = (STexPic *)EF_GetTextureByID(pFrustum->depth_tex_id);
tp->m_RefTex.m_MinFilter = D3DTEXF_LINEAR;
tp->m_RefTex.m_MagFilter = D3DTEXF_LINEAR;
}
}