#include "stdafx.h" #include "SWaterViewPort.h" #include "KPrimitive.h" #include "KRenderDeviceDX.h" #include #include namespace { K3DTexture* CreateWaterBumpMap(K3DRenderDevice* dev, DWORD dwWidth, DWORD dwHeight) { if(dev == NULL) return NULL; K3DTexture* psBumpMap; // Create the bump map texture if( FAILED( psBumpMap = dev->CreateTexture( dwWidth, dwHeight, K3DFMT_V8U8 ) ) ) return NULL; // Lock the surface and write in some bumps for the waves //D3DLOCKED_RECT d3dlr; CHAR* pDst; int nStride; CHAR iDu, iDv; psBumpMap->LockRect( NULL, (void **)&pDst, nStride ); if(!pDst) { // assert(0 && "psBumpMap->LockRect( NULL, (void **)&pDst, nStride );"); return NULL; } //pDst = (CHAR*)d3dlr.pBits; for( DWORD y=0; yUnlock(); return psBumpMap; } K3DTexture* CreateBumpMap(K3DRenderDevice* dev, const char* src, int width, int height) { if(dev == NULL) return NULL; if(src == NULL) return NULL; LPDIRECT3DTEXTURE9 psBumpSrc = NULL; HRESULT res; D3DXIMAGE_INFO infoImg; int strlength = (int)strlen(src); res = D3DXGetImageInfoFromFile( src, &infoImg ); res = D3DXCreateTextureFromFileEx( ((K3DRenderDeviceDX*)dev)->GetD3DDevice(), src, infoImg.Width, infoImg.Height, 0, 0, D3DFMT_UNKNOWN, D3DPOOL_SYSTEMMEM, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &psBumpSrc ); if( !psBumpSrc ) return NULL; K3DTexture* psBumpDst; int texWidth = infoImg.Width; int texHeight = infoImg.Height; // Create the bumpmap's surface and texture objects // 2010.06.03 - prodongi if( !( psBumpDst = dev->CreateTexture( texWidth, texHeight, K3DFMT_V8U8 ))) //if( FAILED( psBumpDst = dev->CreateTexture( texWidth, texHeight, K3DFMT_V8U8 ) ) ) { return NULL; } // Fill the bits of the new texture surface with bits from // a private format. D3DLOCKED_RECT dxrc; BYTE* pSrcTopRow; int dwSrcPitch; res = psBumpSrc->LockRect( 0, &dxrc, NULL, D3DLOCK_READONLY ); if(res != D3D_OK) { //assert(res == D3D_OK && "res = psBumpSrc->LockRect( 0, &dxrc, NULL, D3DLOCK_READONLY );"); return NULL; } pSrcTopRow = (BYTE *)dxrc.pBits; dwSrcPitch = dxrc.Pitch; BYTE* pSrcCurRow = pSrcTopRow; BYTE* pSrcBotRow = pSrcTopRow + (dwSrcPitch * (texHeight - 1) ); BYTE* pDstTopRow; int dwDstPitch; psBumpDst->LockRect( NULL, (void **)&pDstTopRow, dwDstPitch ); if(!pDstTopRow) { //assert(pDstTopRow && "psBumpDst->LockRect( NULL, (void **)&pDstTopRow, dwDstPitch );"); return NULL; } BYTE* pDstCurRow = pDstTopRow; BYTE* pDstBotRow = pDstTopRow + (dwDstPitch * (texHeight - 1) ); for( int y=0; y1 ) ? 63 : 127; *pDstT++ = (BYTE)iDu; *pDstT++ = (BYTE)iDv; // Move one pixel to the right (src is 32-bpp) pSrcB0+=4; pSrcB1+=4; pSrcB2+=4; } // Move to the next line pSrcCurRow += dwSrcPitch; pDstCurRow += dwDstPitch; } psBumpDst->Unlock(); psBumpSrc->UnlockRect(0); psBumpSrc->Release(); return psBumpDst; } }; SWaterViewPort::SWaterViewPort( bool bClearColorBuffer, bool bClearDepthBuffer) : SViewPort( VIEWPORT_WATER, bClearColorBuffer, bClearDepthBuffer ) { ClearRegisteredList(); int n = 0xffffffff; m_nRenderFlag.CopyFrom( &n ); #ifndef NDEBUG m_bDebugMode = false; #endif m_nWaterQuality = 3; //m_pGameViewport = NULL; m_fHQWaterHeight = 0.f; } SWaterViewPort::~SWaterViewPort() { } void SWaterViewPort::SetWaterQuality(int nQuality) { if(m_spWaterBumpTexture && m_spWaterReflectionTexture && m_nWaterQuality == nQuality) return; if(nQuality < 0 || nQuality > 3) return; std::string src = KFileManager::Instance().CreateTemporaryFileFromResource( "waterbump.bmp" ); switch(nQuality) { case 3: m_spWaterBumpTexture = CreateBumpMap(m_dev, src.c_str(), 512, 512); if(m_spWaterBumpTexture) break; else nQuality = 2; case 2: m_spWaterBumpTexture = CreateBumpMap(m_dev, src.c_str(), 256, 256); if(m_spWaterBumpTexture) break; else nQuality = 1; case 1: m_spWaterBumpTexture = CreateBumpMap(m_dev, src.c_str(), 128, 128); if(m_spWaterBumpTexture) break; else nQuality = 0; } switch(nQuality) { case 3: //m_spWaterReflectionTexture = m_dev->CreateRenderTarget( 512, 512, 1, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_ENABLE ); //if(m_spWaterReflectionTexture == NULL) // m_spWaterReflectionTexture = m_dev->CreateRenderTarget(512, 512, 1, K3DFMT_R5G6B5, K3DRenderTarget::DEPTH_ENABLE ); m_spWaterReflectionTexture = m_dev->CreateRenderTarget( 512, 512, 1, K3DFMT_X8R8G8B8, K3DRenderTarget::DEPTH_ENABLE ); if(m_spWaterReflectionTexture == NULL) m_spWaterReflectionTexture = m_dev->CreateRenderTarget(512, 512, 1, K3DFMT_A8R8G8B8, K3DRenderTarget::DEPTH_ENABLE ); if(m_spWaterReflectionTexture) break; else nQuality = 2; case 2: m_spWaterReflectionTexture = m_dev->CreateRenderTarget( 256, 256, 1, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_ENABLE ); if(m_spWaterReflectionTexture == NULL) m_spWaterReflectionTexture = m_dev->CreateRenderTarget(256, 256, 1, K3DFMT_R5G6B5, K3DRenderTarget::DEPTH_ENABLE ); if(m_spWaterReflectionTexture) break; else nQuality = 1; case 1: m_spWaterReflectionTexture = m_dev->CreateRenderTarget( 128, 128, 1, K3DFMT_X1R5G5B5, K3DRenderTarget::DEPTH_ENABLE ); if(m_spWaterReflectionTexture == NULL) m_spWaterReflectionTexture = m_dev->CreateRenderTarget(128, 128, 1, K3DFMT_R5G6B5, K3DRenderTarget::DEPTH_ENABLE ); if(m_spWaterReflectionTexture) break; else nQuality = 0; } if(nQuality != 0) { assert(m_spWaterReflectionTexture != NULL && "Water Reflection Texture 생성실패"); assert(m_spWaterBumpTexture != NULL && "Water Bump Texture 생성실패"); } m_nWaterQuality = nQuality; } void SWaterViewPort::Initilaize( K3DRenderDevice *dev, const KViewportStruct &viewarea, float nearClip, float farClip ) { SViewPort::Initilaize( dev, viewarea, nearClip, farClip ); m_fVertexAspectForWater = dev->GetScreenVertexAspect(); SetWaterQuality(m_nWaterQuality); } void SWaterViewPort::SetCamera( const K3DCamera *cam ) { /*// Reset camera & it's matrix m_vCamPos = GetCameraPos(); m_vTarPos = GetCameraTargetPos(); float val = (m_fHQWaterHeight - m_vCamPos.z)/(m_vTarPos.z - m_vCamPos.z); m_vTarPos = val*m_vTarPos + (1 - val)*m_vCamPos; m_vCamPos.z -= (m_vCamPos.z - m_fHQWaterHeight)*2; //SetSceneState(m_fFieldofView, m_fScrWidth/m_fScrHeight, m_fDepthNear, m_fDepthFar, true, false, D3DXVECTOR3(0, 0, -1)); K3DMatrixPerspectiveFovLH( &m_matProjection, m_pViewCamera->GetFOV(), GetVertexAspect(), GetNearClip(), GetFarClip() ); K3DMatrixLookAtLH(&m_matView, &m_vCamPos, &m_vTarPos, &(-m_pViewCamera->GetUpVector()));*/ // 반사에 맞게 변형 K3DCamera t_cam = *cam; K3DVector campos = cam->GetCamPos(); K3DVector tarpos = cam->GetTargetPos(); K3DVector upvector = cam->GetUpVector(); float val = (m_fHQWaterHeight - campos.z)/(tarpos.z - campos.z); tarpos = val*tarpos + (1 - val)*campos; campos.z -= (campos.z - m_fHQWaterHeight)*2; //t_cam.SetCoordinateToLeftHand(); t_cam.SetCamPos(campos.x, campos.y, campos.z); t_cam.SetTargetPos(tarpos.x, tarpos.y, tarpos.z); t_cam.SetUpVector(-upvector.x, -upvector.y, -upvector.z); SViewPort::SetCamera(&t_cam); //SViewPort::SetCamera(cam); } void SWaterViewPort::ClearRegisteredList() { SViewPort::ClearRegisteredList(); } void SWaterViewPort::Register( K3DPrimitive *pr, DWORD flag ) { if( m_bUseViewPort == false ) return; // flag 참조하여 필요없는 것은 패스 시킨다. SViewPort::Register(pr, flag); } void SWaterViewPort::Render( bool bClearRegister /*= true*/, bool bSetRenderTarget /*= true*/ ) { START_RENDER_VIEWPORT("Water Viweport"); m_bLocalCoord = false; if( m_bUseViewPort == false ) return; if(m_nWaterQuality < 1) return; KViewportStruct backview = m_viewport; //뷰포트 설정 m_viewport.X = 0; m_viewport.Y = 0; m_viewport.Width = m_spWaterReflectionTexture->GetWidth() -1; m_viewport.Height = m_spWaterReflectionTexture->GetHeight()-1; m_viewport.MinZ = 0; m_viewport.MaxZ = 1; // Render Target 변경 m_dev->SetRenderTarget(m_spWaterReflectionTexture); /*{ // Reset camera & it's matrix m_vCamPos = GetCameraPos(); m_vTarPos = GetCameraTargetPos(); float val = (m_fHQWaterHeight - m_vCamPos.z)/(m_vTarPos.z - m_vCamPos.z); m_vTarPos = val*m_vTarPos + (1 - val)*m_vCamPos; m_vCamPos.z -= (m_vCamPos.z - m_fHQWaterHeight)*2; //SetSceneState(m_fFieldofView, m_fScrWidth/m_fScrHeight, m_fDepthNear, m_fDepthFar, true, false, D3DXVECTOR3(0, 0, -1)); K3DMatrixPerspectiveFovRH( &m_matProjection, m_ViewCamera.GetFOV(), GetVertexAspect(), GetNearClip(), GetFarClip() ); K3DMatrixLookAtRH(&m_matView, &m_vCamPos, &m_vTarPos, &(-m_ViewCamera.GetUpVector())); }*/ { static float s_fWaterHeightOffset = 0.0f; K3DMatrix mattemp = m_matView*m_matProjection; K3DVector a(m_vCamPos.x, m_vCamPos.y, m_fHQWaterHeight - s_fWaterHeightOffset), b(m_vCamPos.x+1000, m_vCamPos.y+1000, m_fHQWaterHeight - s_fWaterHeightOffset), c(m_vCamPos.x, m_vCamPos.y+1000, m_fHQWaterHeight - s_fWaterHeightOffset); K3DVectorTransform(a, a, mattemp); K3DVectorTransform(b, b, mattemp); K3DVectorTransform(c, c, mattemp); K3DPlane clip_plane; K3DPlaneFromPoints( clip_plane, a, c, b ); if(clip_plane.d > 0) K3DPlaneFromPoints( clip_plane, a, b, c ); m_dev->SetClipPlane(0, clip_plane); m_dev->SetClipPlaneMode(K3DRenderDevice::CPM_USER1); } m_dev->SetCullMode(K3DRenderDevice::KCM_CCW); //TODO : 물 높이의 하늘 색과 같은 칼라 구하기 추가 해야 함. SetFillColor( KColor( (unsigned char)(m_SkyColorEnd.r*255.f), (unsigned char)(m_SkyColorEnd.g*255.f), (unsigned char)(m_SkyColorEnd.b*255.f), (unsigned char)(1.0f) // 255가 아닐까? ;; ) // KColor(215,222,255,255) ); BeginRender(); //float fOldClipOffsetRatio = GetClipOffsetRatio(); static float s_fClipOffsetRatio = -0.2f; SetClipOffsetRatio( s_fClipOffsetRatio ); float fOldMipBias = m_dev->GetMipBias(); m_dev->SetMipBias( fOldMipBias + ( fOldMipBias + 1.0f ) * 0.5f ); // fog off // m_dev->SetFogMode( K3DRenderDevice::FOGM_NONE, 0, 0, 0 ); m_dev->SetCullMode( K3DRenderDevice::KCM_CCW ); RenderSky(); m_dev->SetCullMode( K3DRenderDevice::KCM_NONE ); RenderCloud(); if ( m_fogMode != K3DRenderDevice::FOGM_NONE ) { m_dev->SetFogMode( m_fogMode, m_fogColor, m_fogFactor1, m_fogFactor2, m_fogFactor3, m_fogFactor4 ); } m_dev->SetCullMode( K3DRenderDevice::KCM_CCW ); { RenderTerrain( true ); } { //float scale = 1/SShadowViewPort::SHADOW_RATIO; //m_dev->SetVertexShaderConstant(CONSTANT_TERRAIN1STTEXTURESCALE, &scale, 1); //m_dev->SetVertexShaderConstant(CONSTANT_TERRAIN2NDTEXTURESCALE, &scale, 1); //m_dev->SetVertexShaderConstant(CONSTANT_TERRAIN3THTEXTURESCALE, &scale, 1); //m_dev->SetVertexShaderConstant(CONSTANT_TERRAIN4THTEXTURESCALE, &scale, 1); //float center[4] = { +GetCameraTargetPos().x-SHADOW_RATIO/2, +GetCameraTargetPos().y-SHADOW_RATIO/2, GetCameraTargetPos().z, 0 }; //m_dev->SetVertexShaderConstant(CONSTANT_TERRAINTEXTURECENTER, center, 4); } //RenderTerrainShadow(); m_dev->SetRenderState( K3DRenderDevice::RS_DEFAULT ); /*RenderBuilding(NULL, NULL); RenderAlphaBuilding(NULL, NULL); */ m_dev->SetDepthBufferWriteEnable( true ); m_dev->SetDepthBufferCompareMode( K3DRenderDevice::DCM_LESSEQUAL ); m_dev->SetCullMode(K3DRenderDevice::KCM_CW); { RenderBranch(); m_dev->SetCullMode(K3DRenderDevice::KCM_NONE); RenderFrond(); RenderLeaf(); RenderTreeBillboard(); } { //RenderPathEffect(); RenderQuadPrimitive(); RenderLinePrimitive(); RenderPolyLinePrimitive(); m_dev->SetVertexShaderDefault(); m_dev->SetCullMode( K3DRenderDevice::KCM_CCW ); m_dev->SetDepthBufferWriteEnable( true ); m_dev->SetDepthBufferCompareMode( K3DRenderDevice::DCM_LESSEQUAL ); /*RenderProp(NULL, NULL); RenderAlphaProp(NULL, NULL); RenderPrNoLightList(); */ if ( m_fogMode != K3DRenderDevice::FOGM_NONE ) { m_dev->SetFogMode( m_fogMode, m_fogColor, m_fogFactor1, m_fogFactor2, m_fogFactor3, m_fogFactor4 ); } /*RenderPrVSList(); RenderPrVSListSpecularList(); RenderPrList(); RenderPrListSpecularList(); */ RenderPrList(m_prMesh, NULL, NULL); // fog off m_dev->SetFogMode( K3DRenderDevice::FOGM_NONE, 0, 0, 0, 0, 0 ); /*RenderPrNoFogList(); if ( m_fogMode != K3DRenderDevice::FOGM_NONE ) { m_dev->SetFogMode( m_fogMode, m_fogColor, m_fogFactor1, m_fogFactor2, m_fogFactor3, m_fogFactor4 ); } /*RenderPrVSAlphaList(); RenderPrAlphaList(); RenderPrVSAlphaSpecularList(); */ RenderPrAlphaList(m_prTransMesh, NULL, NULL); m_dev->SetFogMode( K3DRenderDevice::FOGM_NONE, m_fogColor, m_fogFactor1, m_fogFactor2, m_fogFactor3, m_fogFactor4 ); m_dev->SetCullMode(K3DRenderDevice::KCM_NONE); RenderBliiboardList(); m_dev->SetCullMode(K3DRenderDevice::KCM_CCW); /*RenderPrNoFogAlphaList(); RenderAdditiveBuilding(NULL, NULL); RenderAdditiveProp(NULL, NULL); */ } //버그땜시 잠시제거 { RenderAdditiveBliiboard(); } { RenderSpeedGrass(); } //if( NULL != m_pChildViewportObj ) // m_pChildViewportObj->Render( bClearRegister ); m_dev->SetCullMode(K3DRenderDevice::KCM_CCW); // Render Target 복구 m_dev->SetRenderTarget(NULL); m_dev->SetClipPlaneMode(0); m_viewport = backview; m_dev->SetViewport( m_viewport ); //D3DXSaveTextureToFile("c:\\water_reflection.bmp", D3DXIFF_BMP, ((K3DRenderTargetDX*)m_spWaterReflectionTexture)->GetD3DTexture(), NULL); if( 0 != HIBYTE(GetAsyncKeyState(VK_RSHIFT)) ) { _oprint( "ViewPort Water - DP Count : %d\n", ((K3DRenderDeviceDX*)m_dev)->GetDPCount() ); } EndRender(bClearRegister); m_dev->SetMipBias( fOldMipBias ); //SetClipOffsetRatio( fOldClipOffsetRatio ); }