#include "stdafx.h" #include "SShadowViewPort.h" #include "KPrimitive.h" #include "KRenderDeviceDX.h" #include #include 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 ; iGetVSMode()) 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 ; iGetVSMode()) 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; }