Files
Leviathan/Client/Game/game/Main/SShadowViewPort.cpp
T
2026-06-01 12:46:52 +02:00

784 lines
23 KiB
C++

#include "stdafx.h"
#include "SShadowViewPort.h"
#include "KPrimitive.h"
#include "KRenderDeviceDX.h"
#include <dump/XException.h>
#include <kfile/KFileManager.h>
float SShadowViewPort::SHADOW_RATIO = 256.f;
SShadowViewPort::SShadowViewPort( bool bClearColorBuffer, bool bClearDepthBuffer)
: SViewPort( VIEWPORT_SHADOW, bClearColorBuffer, bClearDepthBuffer )
{
//Shadow
m_fShadowBottomHeight = 99999.f;
m_bIsValid = false;
#ifndef NDEBUG
m_bDebugMode = false;
#endif
//m_bUseShadowBuffer = true;
//m_bUseShadowBuffer = false;
m_nShadowBufferQuality = 0;
//m_nShadowBufferQuality = 3;
m_nShadowMapQuality = 3;
m_nJitterMapQuality = 3;
//m_pGameViewport = NULL;
m_nUseSpecular = TRUE;
}
SShadowViewPort::~SShadowViewPort()
{
}
void SShadowViewPort::SetShadowBufferQuality(int nQuality)
{
if(m_spShadowBuffer != NULL && m_nShadowBufferQuality == nQuality) return;
if(nQuality < 0 || nQuality > 3) return;
switch(nQuality)
{
case 3:
m_spShadowBuffer = m_dev->CreateRenderTarget( 2048, 2048, 1, K3DFMT_R32F, K3DRenderTarget::DEPTH_ENABLE );
//m_spShadowBuffer = m_dev->CreateRenderTarget( 2048, 2048, 1, K3DFMT_R32F, K3DRenderTarget::DEPTH_USEASTEXTURE );
if(m_spShadowBuffer != NULL) break;
else nQuality = 2;
case 2:
m_spShadowBuffer = m_dev->CreateRenderTarget( 1024, 1024, 1, K3DFMT_R32F, K3DRenderTarget::DEPTH_ENABLE );
//m_spShadowBuffer = m_dev->CreateRenderTarget( 1024, 1024, 1, K3DFMT_R32F, K3DRenderTarget::DEPTH_USEASTEXTURE );
if(m_spShadowBuffer != NULL) break;
else nQuality = 1;
case 1:
m_spShadowBuffer = m_dev->CreateRenderTarget( 512, 512, 1, K3DFMT_R32F, K3DRenderTarget::DEPTH_ENABLE );
//m_spShadowBuffer = m_dev->CreateRenderTarget( 512, 512, 1, K3DFMT_R32F, K3DRenderTarget::DEPTH_USEASTEXTURE );
if(m_spShadowBuffer != NULL) break;
else nQuality = 0;
}
if(nQuality != 0)
{
assert(m_spShadowBuffer != NULL && "Shadow Buffer 생성실패");
}
m_nShadowBufferQuality = nQuality;
}
void SShadowViewPort::SetShadowMapQuality(int nQuality)
{
if(m_spShadowMap != NULL && m_nShadowMapQuality == nQuality) return;
if(nQuality < 0 || nQuality > 3) return;
switch(nQuality)
{
case 3:
//m_spShadowMap = m_dev->CreateRenderTarget( 1024, 1024, 4, K3DFMT_X1R5G5B5, false );
m_spShadowMap = m_dev->CreateRenderTarget( 1024, 1024, 4, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_DISABLE );
if(m_spShadowMap != NULL) break;
else nQuality = 2;
case 2:
//m_spShadowMap = m_dev->CreateRenderTarget( 512, 512, 2, K3DFMT_X1R5G5B5, false );
m_spShadowMap = m_dev->CreateRenderTarget( 512, 512, 2, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_DISABLE );
if(m_spShadowMap!= NULL) break;
else nQuality = 1;
case 1:
//m_spShadowMap = m_dev->CreateRenderTarget( 256, 256, 1, K3DFMT_X1R5G5B5, false );
m_spShadowMap = m_dev->CreateRenderTarget( 256, 256, 1, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_DISABLE );
if(m_spShadowMap!= NULL) break;
else nQuality = 0;
}
if(nQuality != 0)
{
assert(m_spShadowMap != NULL && "Shadow Map 생성실패");
}
m_nShadowMapQuality = nQuality;
}
void SShadowViewPort::SetJitterMapQuality(int nQuality)
{
if(m_spShadowJitterMap != NULL && m_nJitterMapQuality == nQuality) return;
if(nQuality < 0 || nQuality > 3) return;
switch(nQuality)
{
case 3:
//m_spShadowJitterMap = m_dev->CreateRenderTarget(1024, 1024, 1, K3DFMT_X1R5G5B5, false );
m_spShadowJitterMap = m_dev->CreateRenderTarget(1024, 1024, 1, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_DISABLE );
if(m_spShadowJitterMap != NULL) break;
else nQuality = 2;
case 2:
//m_spShadowJitterMap = m_dev->CreateRenderTarget(512, 512, 1, K3DFMT_X1R5G5B5, false );
m_spShadowJitterMap = m_dev->CreateRenderTarget(512, 512, 1, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_DISABLE );
if(m_spShadowJitterMap != NULL) break;
else nQuality = 1;
case 1:
//m_spShadowJitterMap = m_dev->CreateRenderTarget(256, 256, 1, K3DFMT_X1R5G5B5, false );
m_spShadowJitterMap = m_dev->CreateRenderTarget(256, 256, 1, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_DISABLE );
if(m_spShadowJitterMap != NULL) break;
else nQuality = 0;
}
if(nQuality != 0)
{
assert(m_spShadowJitterMap != NULL && "Jitter Map 생성실패");
}
m_nJitterMapQuality = nQuality;
}
void SShadowViewPort::ClearAllShadowMap()
{
m_spShadowMap = NULL;
m_spShadowBuffer = NULL;
m_spShadowJitterMap = NULL;
}
void SShadowViewPort::ReCreateAllShadowMap()
{
SetShadowBufferQuality(m_nShadowBufferQuality);
SetShadowMapQuality(m_nShadowMapQuality);
SetJitterMapQuality(m_nJitterMapQuality);
}
void SShadowViewPort::Initilaize( K3DRenderDevice *dev, const KViewportStruct &viewarea, float nearClip, float farClip )
{
SViewPort::Initilaize( dev, viewarea, nearClip, farClip );
m_nShadowStride = 0;
//#ifndef NDEBUG
//m_spShadowBuffer = m_dev->CreateRenderTarget( 2048, 2048, 1, K3DFMT_R32F, true );
//assert(m_spShadowBuffer != NULL && " Shadow Buffer 생성실패");
//m_spShadowMap = m_dev->CreateRenderTarget( 1024, 1024, 4, K3DFMT_X1R5G5B5, false );
//if(m_spShadowMap == NULL)
// m_spShadowMap = m_dev->CreateRenderTarget(1024, 1024, 2, K3DFMT_R5G6B5, false );
//assert(m_spShadowMap != NULL && "Shadow Render Target 생성 실패");
//m_spShadowJitterMap = m_dev->CreateRenderTarget(1024, 1024, 1, K3DFMT_X1R5G5B5, false );
//if(m_spShadowJitterMap == NULL)
// m_spShadowJitterMap = m_dev->CreateRenderTarget(1024, 1024, 1, K3DFMT_R5G6B5, false );
//assert(m_spShadowJitterMap != NULL && "Shadow Jitter Map 생성 실패");
ReCreateAllShadowMap();
m_spShadowVB = m_dev->CreateVertexBuffer( VERTEX_LENS, 4 );
if( m_spShadowVB && m_spShadowVB->IsValidVtx() )
{
m_nShadowStride = K3DVertexBuffer::CalcVertexStride( VERTEX_LENS );
float fWidth, fHeight;
fWidth = 1024;
fHeight = 1024;
K3DVERTEX_LENS *pTempBuf = NULL;
int size = 4; //Size 사용 안함.
m_spShadowVB->Lock( (void**)&pTempBuf, size );
assert(pTempBuf && "m_spShadowVB->Lock( (void**)&pTempBuf, size );");
if( pTempBuf )
{
pTempBuf[0].p = D3DXVECTOR3( 0, 0, 0.5f ); pTempBuf[0].rhw = 1.f;
pTempBuf[0].tu = 0.f; pTempBuf[0].tv = 0.f;
pTempBuf[1].p = D3DXVECTOR3( fWidth, 0, 0.5f ); pTempBuf[1].rhw = 1.f;
pTempBuf[1].tu = 1.f; pTempBuf[1].tv = 0.f;
pTempBuf[2].p = D3DXVECTOR3( 0, fHeight, 0.5f ); pTempBuf[2].rhw = 1.f;
pTempBuf[2].tu = 0.f; pTempBuf[2].tv = 1.f;
pTempBuf[3].p = D3DXVECTOR3( fWidth, fHeight, 0.5f ); pTempBuf[3].rhw = 1.f;
pTempBuf[3].tu = 1.f; pTempBuf[3].tv = 1.f;
pTempBuf[0].color = D3DCOLOR_RGBA(255,255,255,255); //농도
pTempBuf[1].color = D3DCOLOR_RGBA(255,255,255,255); //농도
pTempBuf[2].color = D3DCOLOR_RGBA(255,255,255,255); //농도
pTempBuf[3].color = D3DCOLOR_RGBA(255,255,255,255); //농도
m_spShadowVB->Unlock();
}
}
//#endif
}
void SShadowViewPort::SetCamera( const K3DCamera *cam )
{
//{
// // transform
// K3DMatrix view, proj, viewproj;
// K3DMatrixOrthoLH( &proj, SHADOW_RATIO, SHADOW_RATIO, 10.f, 4000.f );
// //카메라 정보로 타겟위치에 대한 프러스텀을 하나 만든다.
// K3DVector scenter;
// K3DVectorNomalize(&scenter, &(m_vTarPos - m_vCamPos));
// scenter = /*10*scenter +*/ m_vTarPos;
// K3DVector pos1(scenter.x, scenter.y, 1200); //하늘 위치
// K3DVector pos2(pos1.x, pos1.y, -1000); //땅의 위치
// K3DMatrixLookAtLH(&view, &pos1, &pos2, &K3DVector(0, -1, 0)); //텍스쳐의 방향이 뒤집어 진다.
// m_dev->SetTransform(K3DRenderDevice::TS_PROJECTION, proj);
// m_dev->SetTransform(K3DRenderDevice::TS_VIEW , view);
//}
m_vCameraTargetPos_Backup = cam->GetTargetPos();
// 반사에 맞게 변형
K3DCamera t_cam = *cam;
K3DVector campos = cam->GetCamPos();
K3DVector tarpos = cam->GetTargetPos();
//K3DVector upvector = cam->GetUpVector();
// 프로젝션 그림자
{
K3DVector scenter;
scenter = tarpos;
campos = K3DVector(scenter.x, scenter.y, scenter.z+1200); //하늘 위치
tarpos = K3DVector(scenter.x, scenter.y, scenter.z-1000); //땅의 위치
}
// shadow buffer
/*{
//assert(GetLight(0) != NULL && "setting light prior to camera");
if(GetLight(0))
campos = tarpos - 100*GetLight(0)->direction;
else
campos = tarpos - 100*K3DVector(-0.33f,-0.66f,-0.66f);
}*/
SetClipRange(10, 4000); // AziaMafia LoadMap SetClipRange(10, 4000);
t_cam.SetCoordinateToLeftHand();
t_cam.SetCameraOrthogonalMode();
t_cam.SetFOV(SHADOW_RATIO);
t_cam.SetCamPos(campos.x, campos.y, campos.z);
t_cam.SetTargetPos(tarpos.x, tarpos.y, tarpos.z);
t_cam.SetUpVector(0, -1, 0);
SViewPort::SetCamera(&t_cam);
//SViewPort::SetCamera(cam);
}
void SShadowViewPort::Register( K3DPrimitive *pr, DWORD flag )
{
SViewPort::Register(pr, flag);
DWORD r_flag = LOWORD(flag);
// RENDEREFX_SHADOW 플래그를 달고 오지않는 이상 추가하지않는다.
if( r_flag == KRenderObject::RENDEREFX_NONE ||
r_flag == KRenderObject::RENDEREFX_TERRAIN ||
r_flag == KRenderObject::RENDEREFX_PROP ||
//r_flag == KRenderObject::RENDEREFX_PROP_HAS_STOOL ||
r_flag == KRenderObject::RENDEREFX_SHADOW ||
r_flag == KRenderObject::RENDEREFX_BUILDING ||
r_flag == KRenderObject::RENDEREFX_BUILDING_HAS_STOOL )
{
if( r_flag >= KRenderObject::RENDEREFX_NONE && r_flag < KRenderObject::RENDEREFX_MAX )
{
float depth = (float)pr->GetMagicNumber() + 0;
RENDER_MESHEX container;
if( AllocNewMeshEX( container, pr, LOWORD(flag), 0, pr->IsBump(), pr->IsSpecular(), pr->GetVSMode(), false, depth ) )
{
DWORD shadow_flag = HIWORD(flag);
if( shadow_flag & SHADOW_DY_CAST )
m_vRenderList.insert( container );
}
}
else
{
assert(0 && "Render Flag 이상함" );
}
}
}
void SShadowViewPort::ClearRegisteredList()
{
m_vRenderList.clear();
//m_fShadowBottomHeight = 99999.f;
SViewPort::ClearRegisteredList();
}
namespace {
float shadowjittervtx[] = {
0 , 0, 0, 0, 1, -0.0012f, 1-0.0012f, 0.0012f, 1+0.0012f,
2048, 0, 0, 1, 1, 1-0.0012f, 1-0.0012f, 1+0.0012f, 1+0.0012f,
2048, 2048, 0, 1, 0, 1-0.0012f, -0.0012f, 1+0.0012f, 0.0012f,
2048, 2048, 0, 1, 0, 1-0.0012f, -0.0012f, 1+0.0012f, 0.0012f,
0 , 2048, 0, 0, 0, -0.0012f, -0.0012f, 0.0012f, 0.0012f,
0 , 0, 0, 0, 1, -0.0012f, 1-0.0012f, 0.0012f, 1+0.0012f,
};
//void SetShadowTransform(K3DPrimitive *pr, const K3DVector &litdir, float baseheight, bool bLocalCoord, K3DVector vLocalOffset)
void SetShadowTransform(K3DPrimitive *pr, const K3DVector &litdir, float baseheight)
{
//K3DVector litdir = litpos - *(K3DVector *)&pr->GetTransform()->_41;
//Normalize(litdir);
K3DMatrix litmat, rootmat = *pr->GetRootMat();
//if(bLocalCoord)
//{
// K3DVector vecTrans;
// K3DMatrixGetPosVector(vecTrans, rootmat);
// vecTrans -= vLocalOffset;
// K3DMatrixSetPosVector(rootmat, vecTrans);
// baseheight -= vLocalOffset.z;
//}
K3DMatrixIdentity(litmat);
litmat._31 = litdir.x;
litmat._32 = litdir.y;
litmat._33 = -litdir.z;
rootmat._43 -= baseheight;
//rootmat._43 = 0;
K3DMatrix rmat = rootmat*litmat;
pr->SetRootMat(&rmat);
}
};
void SShadowViewPort::SetShadowBottomHeight(float height)
{
m_fShadowBottomHeight = height;
}
void SShadowViewPort::DrawObjectAsShadowBuffer( KSortVector< RENDER_MESHEX > & vList )
{
m_dev->SetRenderState( K3DRenderDevice::RS_DISABLE_UVTRANSFORM );
m_dev->SetTexture( 1, NULL );
m_dev->SetTexture( 2, NULL );
m_dev->SetTexture( 3, NULL );
START_DPCOUNT("Shadow Buffer");
for ( int i=0 ; i<vList.size(); ++i )
{
if(vList[i].primitive->GetVSMode())
m_dev->SetVertexShader(VTXDECLARATION_SKINMESH, TECHNIQUE_SHADOWBUFFER);
else
m_dev->SetVertexShader(VTXDECLARATION_OBJECTMESH, TECHNIQUE_SHADOWBUFFER);
vList[i].primitive->Render( this, m_dev, false );
}
END_DPCOUNT();
}
void SShadowViewPort::DrawObjectAsShadow( KSortVector< RENDER_MESHEX > & vList )
{
m_dev->SetRenderState( K3DRenderDevice::RS_DISABLE_UVTRANSFORM );
m_dev->SetTexture( 1, NULL );
m_dev->SetTexture( 2, NULL );
m_dev->SetTexture( 3, NULL );
static enum STATE_OBJECT
{
STATE_INIT = 0,
STATE_VS,
STATE_FIX,
};
STATE_OBJECT oldState = STATE_INIT;
STATE_OBJECT newState = STATE_INIT;
START_DPCOUNT("Shadow");
for ( int i=0 ; i<vList.size(); ++i )
{
if(vList[i].primitive->GetVSMode()) newState = STATE_VS;
else newState = STATE_FIX;
if( newState != oldState )
{
switch( newState )
{
case STATE_VS:
{
m_dev->SetVertexShader(VTXDECLARATION_SKINMESH, TECHNIQUE_SKINMESH);
float fFactor = GetSkinAmbientFactor();
m_dev->SetVertexShaderConstant(CONSTANT_AMBIENT_FACTOR, &fFactor, 1);
fFactor = GetSkinDiffuseFactor();
m_dev->SetVertexShaderConstant(CONSTANT_DIFFUSE_FACTOR, &fFactor, 1);
}
break;
case STATE_FIX:
{
m_dev->SetVertexShader(VTXDECLARATION_OBJECTMESH, TECHNIQUE_OBJECTMESH);
}
break;
}
oldState = newState;
}
K3DMatrix back_rmat = *vList[i].primitive->GetRootMat();
const K3DLight *lit = GetLight(vList[i].primitive->GetLightIndex());
if( lit )
{
SetShadowTransform(vList[i].primitive, lit->direction, m_fShadowBottomHeight);
vList[i].primitive->Render( this, m_dev, false );
vList[i].primitive->SetRootMat(&back_rmat);
}
}
END_DPCOUNT();
}
bool SShadowViewPort::RenderShadowBuffer()
{
if ( m_vRenderList.size() <= 0 ) return false;
if( !m_spShadowBuffer ) return false;
KViewportStruct backview = m_viewport;
m_dev->SetRenderTarget( m_spShadowBuffer );
//m_dev->SetBackBufferWriteEnable(0);
m_dev->SetDepthBufferWriteEnable( true );
m_dev->BeginScene();
//뷰포트 설정
m_viewport.X = 1;
m_viewport.Y = 1;
m_viewport.Width = m_spShadowBuffer->GetWidth() -2;
m_viewport.Height = m_spShadowBuffer->GetHeight()-2;
m_viewport.MinZ = 0;
m_viewport.MaxZ = 1;
//전체 삭제
int option = 0;
option = K3DRenderDevice::FILL_COLOR | K3DRenderDevice::FILL_DEPTH;
//option = K3DRenderDevice::FILL_DEPTH;
m_dev->SetFillColor( KColor(255,255,255,128) );
m_dev->Fill(option);
//1) 카메라 타겟위치, 카메라 위치 정보 필요
// K3DLight * pLight = m_dev->GetLight(0);
K3DCamera back_cam = m_ViewCamera;
// 그림자를 그린다.
// if( pLight )
{
// 반사에 맞게 변형
K3DCamera t_cam = m_ViewCamera;
K3DVector campos;
K3DVector tarpos = m_vCameraTargetPos_Backup;
{
if(GetLight(0))
campos = tarpos - 100*GetLight(0)->direction;
else
campos = tarpos - 100*K3DVector(-0.33f,-0.66f,-0.66f);
}
SetClipRange(10, 165); // AziaMafia LoadMap SetClipRange(10, 165);
//t_cam.SetCoordinateToLeftHand();
t_cam.SetCoordinateToRightHand();
t_cam.SetCameraOrthogonalMode();
t_cam.SetFOV(25/*SHADOW_RATIO*/);
t_cam.SetCamPos(campos.x, campos.y, campos.z);
t_cam.SetTargetPos(tarpos.x, tarpos.y, tarpos.z);
//t_cam.SetUpVector(0.0f, -1.0f, 0.0f);
t_cam.SetUpVector(0.0f, 1.0f, 0.0f);
SViewPort::SetCamera(&t_cam);
// transform - Camera의 Transform에 Ortho가 제대로 정의 안되서 임시방편으로
//K3DMatrixOrthoLH( &m_matProjection, SHADOW_RATIO, SHADOW_RATIO, GetNearClip(), GetFarClip() );
//K3DMatrixLookAtLH(&m_matView, &m_vCamPos, &m_vTarPos, &m_ViewCamera.GetUpVector()); //텍스쳐의 방향이 뒤집어 진다.
m_dev->SetTransform(K3DRenderDevice::TS_PROJECTION, &m_matProjection);
m_dev->SetTransform(K3DRenderDevice::TS_VIEW , &m_matView);
K3DMatrix mat;
K3DMatrixMultiply(mat, m_matView, m_matProjection);
m_dev->SetVertexShaderMatrix( MATRIX_VIEWPROJECTION_SB, &mat );
}
//상태 Block으로 뺐다.
m_dev->SetRenderState( K3DRenderDevice::RS_DEFAULT );
// two-sided
m_dev->SetCullMode( K3DRenderDevice::KCM_CCW );
// m_dev->SetFillMode( K3DRenderDevice::FM_SOLID );
//알파 빼고는 모두 사용 하지 않음.
//알파는 잎파리 같은 구멍 뚫린 오브젝트의 그림자 때문에 사용 한다.
// color
//D3DXCOLOR col(1, 1, 1, 1);
////기존에 사용하던, 쉐이더 상수 데이타와 충돌 안 나는지 살펴 보자.
//m_dev->SetVertexShaderConstant(6, (float *)&col, 1); //Ambient
//m_dev->SetVertexShaderConstant(7, (float *)&col, 1); //Diffuse
//m_dev->SetVertexShaderConstant(8, (float *)&col, 1); //Specular
K3DLight light;
K3DColor kcol(1,1,1,1);
light.ambient = kcol;
light.diffuse = kcol;
light.specular = kcol;
light.direction = K3DVector(0,0,-1);
m_dev->SetVertexShaderLight( &light );
// 현재 예외 부분 - RenderState 설정을 렌더 프랙의 외부로 빼내야한다.
m_dev->SetDepthBufferCompareMode( K3DRenderDevice::DCM_LESSEQUAL );
DrawObjectAsShadowBuffer( m_vRenderList );
//static int b = 0;
//if( b )
// D3DXSaveTextureToFile("c:\\shadow.bmp", D3DXIFF_BMP, ((K3DRenderTargetDX*)m_spShadowBuffer)->GetD3DTexture(), NULL);
m_dev->SetRenderTarget( NULL );
m_dev->EndScene();
// m_viewport = backview;
m_dev->SetCullMode(K3DRenderDevice::KCM_CCW);
m_viewport = backview;
//m_dev->SetBackBufferWriteEnable( K3DRenderDevice::BW_ALPHA | K3DRenderDevice::BW_RED | K3DRenderDevice::BW_GREEN | K3DRenderDevice::BW_BLUE );
m_dev->SetRenderTarget( NULL );
SViewPort::SetCamera(&back_cam);
m_bIsValid = true;
return m_bIsValid;
}
bool SShadowViewPort::RenderShadowMap()
{
if( !m_spShadowMap || !m_spShadowJitterMap ) return false;
m_dev->SetRenderState( K3DRenderDevice::RS_SHADOW_MAP );
KViewportStruct backview = m_viewport;
m_dev->SetRenderTarget( m_spShadowMap );
m_dev->BeginScene();
//뷰포트 설정
m_viewport.X = 1;
m_viewport.Y = 1;
m_viewport.Width = m_spShadowMap->GetWidth() -2;
m_viewport.Height = m_spShadowMap->GetHeight()-2;
m_viewport.MinZ = 0;
m_viewport.MaxZ = 1;
//전체 삭제
int option = 0;
option = K3DRenderDevice::FILL_COLOR;
if ( m_vRenderList.size() <= 0 )
{ //클리어는 해준다.
m_dev->SetFillColor( KColor(255,255,255,128) );
m_dev->Fill(option);
m_dev->SetRenderTarget( NULL );
m_dev->EndScene();
return false;
}
m_dev->SetFillColor( KColor(255,255,255,128) );
m_dev->Fill(option);
//1) 카메라 타겟위치, 카메라 위치 정보 필요
// K3DLight * pLight = m_dev->GetLight(0);
K3DCamera back_cam = m_ViewCamera;
// 그림자를 그린다.
// if( pLight )
{
// transform - Camera의 Transform에 Ortho가 제대로 정의 안되서 임시방편으로
//K3DMatrixOrthoLH( &m_matProjection, SHADOW_RATIO, SHADOW_RATIO, GetNearClip(), GetFarClip() );
//K3DMatrixLookAtLH(&m_matView, &m_vCamPos, &m_vTarPos, &m_ViewCamera.GetUpVector()); //텍스쳐의 방향이 뒤집어 진다.
m_dev->SetTransform(K3DRenderDevice::TS_PROJECTION, &m_matProjection);
m_dev->SetTransform(K3DRenderDevice::TS_VIEW , &m_matView);
}
//상태 Block으로 뺐다.
//m_dev->SetTextureFactor( 0x78787878 );
//그림자 강도 조정
//m_dev->SetTextureFactor( 0xC8C8C8C8 );
m_dev->SetTextureFactor( 0x80808080);
// two-sided
m_dev->SetCullMode( K3DRenderDevice::KCM_CCW );
// m_dev->SetFillMode( K3DRenderDevice::FM_SOLID );
//알파 빼고는 모두 사용 하지 않음.
//알파는 잎파리 같은 구멍 뚫린 오브젝트의 그림자 때문에 사용 한다.
// color
//D3DXCOLOR col(1, 1, 1, 1);
////기존에 사용하던, 쉐이더 상수 데이타와 충돌 안 나는지 살펴 보자.
//m_dev->SetVertexShaderConstant(6, (float *)&col, 1); //Ambient
//m_dev->SetVertexShaderConstant(7, (float *)&col, 1); //Diffuse
//m_dev->SetVertexShaderConstant(8, (float *)&col, 1); //Specular
K3DLight light;
K3DColor kcol(1,1,1,1);
light.ambient = kcol;
light.diffuse = kcol;
light.specular = kcol;
light.direction = K3DVector(0,0,-1);
m_dev->SetVertexShaderLight( &light );
// 현재 예외 부분 - RenderState 설정을 렌더 프랙의 외부로 빼내야한다.
DrawObjectAsShadow( m_vRenderList );
// static int b = 0;
// if( b )
// {
// K3DRenderTarget* pShadow = (K3DRenderTarget*)m_spShadowMap;
// D3DXSaveTextureToFile("c:\\shadow.bmp", D3DXIFF_BMP, ((K3DRenderTargetDX*)pShadow)->GetD3DTexture(), NULL);
// }
m_dev->SetRenderTarget( NULL );
m_dev->EndScene();
// m_viewport = backview;
////////////////////////////////////////////////////////////////////////////
////jitter Pass 1
// backview = m_viewport;
m_dev->SetRenderTarget( m_spShadowJitterMap );
m_dev->SetCullMode(K3DRenderDevice::KCM_NONE);
//전체 삭제
option = K3DRenderDevice::FILL_COLOR;
m_dev->SetFillColor( KColor(255,255,255,255) );
m_dev->Fill(option);
//뷰포트 설정
m_viewport.X = 1;
m_viewport.Y = 1;
m_viewport.Width = m_spShadowJitterMap->GetWidth() - 2;
m_viewport.Height = m_spShadowJitterMap->GetWidth() - 2;
m_dev->SetViewport( m_viewport );
m_dev->BeginScene();
{
// transform
K3DMatrix view, proj;
K3DMatrixOrthoOffCenterLH( proj, 0, 2048, 0, 2048, -100.f, 8000.f );
K3DMatrixIdentity(view);
m_dev->SetTransform(K3DRenderDevice::TS_PROJECTION, &proj);
m_dev->SetTransform(K3DRenderDevice::TS_VIEW , &view);
m_dev->SetTransform(K3DRenderDevice::TS_WORLD , &view);
}
m_dev->SetRenderState( K3DRenderDevice::RS_JITTER );
m_dev->SetRenderState( K3DRenderDevice::RS_DISABLE_UVTRANSFORM );
m_dev->SetVertexShaderDefault();
m_dev->SetTexture(0, m_spShadowMap);
m_dev->DrawPrimitiveUP(D3DFVF_XYZ | D3DFVF_TEX3, shadowjittervtx, 2, sizeof(float)*9);
m_dev->SetTexture(0, NULL);
m_dev->SetRenderTarget( NULL );
m_dev->EndScene();
static bool bShadowTexture = false;
if( bShadowTexture )
m_spShadowMap->SaveToFile( "ShadowMap.dds" );
//////////////////////////////////////////////////////////////////////////
////jitter Pass 2
int pow = 1;
option = K3DRenderDevice::FILL_COLOR;
m_dev->SetFillColor( KColor(255,255,255,255) );
m_dev->SetCullMode( K3DRenderDevice::KCM_NONE );
for(int i = 0; i < m_spShadowMap->GetLevel(); ++i)
{
if( !m_dev->SetRenderTarget( i, m_spShadowMap ) )
continue;
m_dev->Fill(option);
m_viewport.Width = m_spShadowMap->GetWidth()/pow - 2;
m_viewport.Height = m_spShadowMap->GetWidth()/pow - 2;
m_dev->SetViewport(m_viewport);
m_dev->BeginScene();
m_dev->SetVertexShaderDefault();
m_dev->SetTexture(0, m_spShadowJitterMap);
m_dev->DrawPrimitiveUP(D3DFVF_XYZ | D3DFVF_TEX3, shadowjittervtx, 2*1, sizeof(float)*9);
m_dev->SetRenderTarget( NULL );
m_dev->EndScene();
pow *= 2;
}
m_dev->SetCullMode(K3DRenderDevice::KCM_CCW);
m_viewport = backview;
m_dev->SetRenderTarget( NULL );
if( bShadowTexture )
m_spShadowJitterMap->SaveToFile( "ShadowJitterMap.dds" );
m_ViewCamera = back_cam;
m_bIsValid = true;
return m_bIsValid;
}
void SShadowViewPort::Render( bool bClearRegister /*= true*/, bool bSetRenderTarget /*= true*/ )
{
START_RENDER_VIEWPORT("Shadow Viweport");
m_bLocalCoord = false;
// BeginRender();
if(m_nShadowMapQuality > 0 && m_nJitterMapQuality > 0) RenderShadowMap();
if(m_nShadowBufferQuality > 0) RenderShadowBuffer();
if( 0 != HIBYTE(GetAsyncKeyState(VK_RSHIFT)) )
{
_oprint( "ViewPort Shadow - DP Count : %d\n", ((K3DRenderDeviceDX*)m_dev)->GetDPCount() );
}
EndRender(bClearRegister);
}
K3DRenderTarget* SShadowViewPort::GetRenderTarget(int index, void* pr)
{
if(index == 1) {
return m_spShadowBuffer;
}
else {
RENDER_MESHEX mesh;
float depth = (float)((K3DPrimitive *)pr)->GetMagicNumber() + 0;
mesh.Set(((K3DPrimitive *)pr), 0, 0, false, false, false, false, depth);
int list_index = m_vRenderList.search_index(mesh);
if(list_index < 0 || (HIWORD(m_vRenderList[list_index].render_flag) & SHADOW_RECV))
return m_spShadowMap;
else
return NULL;
}
}
int SShadowViewPort::GetShadowBufferQuality()
{
return m_nShadowBufferQuality;
}