784 lines
23 KiB
C++
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;
|
|
}
|