#include "StdAfx.h" #include "WaterBody.h" #include "WaterRenderView.h" #include #include #include #include "WaterManager.h" #include "WaterRenderView.h" using namespace SceneCore; NiImplementRTTI(CWaterBody, NiAVObject); CWaterBody::CWaterBody(void) : m_spWaterRenderView(NULL), //m_spRenderer(NULL), m_bInitialized(false), m_spRenderStep(NULL), m_spTexture0(NULL), m_spRTGroup0(NULL), m_spTextureSky(NULL), m_spBumpMap(NULL), m_spRTView(NULL), m_pkRTViewTexProp(NULL), m_spReflectBGRenderClick(NULL), m_spReflectTexRenderClick(NULL), m_pkWaterSurface(NULL), m_spWaterBodyMtl(NULL), m_kPosition(0.0f, 0.0f, 0.0f), m_fSize(0.0f), m_fAlpha(0.0f), m_kColor(0.0f, 0.0f, 0.0f), m_kBumpMapRepeat(1.0f, 1.0f), m_kUVSpeed(0.0f, 0.0f), m_kSaveCameraPos(0.0f, 0.0f, 0.0f), m_kSaveCameraDir(0.0f, 0.0f, 0.0f), m_uiReflectTexSize(512), m_bInVisableArray(false), m_bEnabled(true) { m_spRootScene = NiNew NiNode; CWaterManager::GetInstance()->AddWaterInstance(this); } CWaterBody::~CWaterBody(void) { //CWaterManager::GetInstance()->RemoveWaterInstance(this); } bool CWaterBody::Init(stWaterInitParam& waterInitParam) { // 拷贝参数 m_spWaterRenderView = waterInitParam.pWaterRenderView; //m_spRenderer = waterInitParam.pkRenderer; m_kPosition = waterInitParam.kPosition; m_fSize = waterInitParam.fSize; m_fAlpha = waterInitParam.fAlpha; m_kColor = waterInitParam.kColor; m_spBumpMap = NiSmartPointerCast(NiSourceTexture, waterInitParam.pkBumpTexture); m_spTextureSky = waterInitParam.pkBGSkyTexture; m_kBumpMapRepeat = waterInitParam.kBumpMapRepeat; m_kUVSpeed = waterInitParam.kUVSpeed; m_uiReflectTexSize = waterInitParam.uiReflectTexSize; // 设置变换节点 m_spRootScene->SetTranslate(m_kPosition); m_spRootScene->SetScale(m_fSize); // 创建 render target m_spTexture0 = NiRenderedTexture::Create(m_uiReflectTexSize, m_uiReflectTexSize, NiRenderer::GetRenderer()); if ( !m_spTexture0) { return false; } m_spRTGroup0 = NiRenderTargetGroup::Create( m_spTexture0->GetBuffer(), NiRenderer::GetRenderer(), true, true ); // 创建水面几何体 _CreateWaterBodyGeom(); // 创建全屏 render view _CreateScreenFillingRenderViews(); // 创建 Bumpmap //_CreateBumpMap(m_kNumWaves); // 创建 material 并设置 shader texture m_spWaterBodyMtl = NiSingleShaderMaterial::Create( "WaterBody" ); NIASSERT( m_spWaterBodyMtl); m_pkWaterSurface->ApplyAndSetActiveMaterial(m_spWaterBodyMtl); NiTexturingProperty* pTexProp = NiNew NiTexturingProperty(); NiTexturingProperty::ShaderMap* pShaderMap = NiNew NiTexturingProperty::ShaderMap( m_spTexture0, 0 ); pTexProp->SetShaderMap(0, pShaderMap); // reflect texture NiTexturingProperty::ShaderMap* pShaderMapBump = NiNew NiTexturingProperty::ShaderMap( m_spBumpMap, 1 ); pTexProp->SetShaderMap(1, pShaderMapBump); // 设置 bump texture m_pkWaterSurface->AttachProperty( pTexProp ); NiAlphaProperty* pAlphaProperty = NiNew NiAlphaProperty(); pAlphaProperty->SetAlphaBlending(true); pAlphaProperty->SetAlphaTesting(false); pAlphaProperty->SetSrcBlendMode(NiAlphaProperty::ALPHA_SRCALPHA); pAlphaProperty->SetDestBlendMode(NiAlphaProperty::ALPHA_INVSRCALPHA); m_pkWaterSurface->AttachProperty( pAlphaProperty ); // 设置 extra data NiPoint3 vPoint = NiPoint3::ZERO; NiFloatsExtraData *pkWaterColor = NiNew NiFloatsExtraData( 3, (float *)&m_kColor.r ); m_pkWaterSurface->AddExtraData( "WaterColor", pkWaterColor ); NiFloatExtraData *pkWaterAlpha = NiNew NiFloatExtraData( m_fAlpha ); m_pkWaterSurface->AddExtraData( "WaterAlpha", pkWaterAlpha ); NiFloatsExtraData *pkBumpMatrix = NiNew NiFloatsExtraData( 4, (float *)&m_kBumpMat.m_fX ); m_pkWaterSurface->AddExtraData( "BumpMatrix", pkBumpMatrix ); NiFloatsExtraData *pkBumpMapRepeat = NiNew NiFloatsExtraData( 2, (float *)&m_kBumpMapRepeat.x ); m_pkWaterSurface->AddExtraData( "BumpMapRepeat", pkBumpMapRepeat ); NiFloatsExtraData *pkBumpMapOffset = NiNew NiFloatsExtraData( 2, (float *)&m_kUVSpeed.x ); m_pkWaterSurface->AddExtraData( "BumpMapOffset", pkBumpMapOffset ); m_pkWaterSurface->Update(0.0f); m_spRootScene->Update(0.0f); m_pkWaterSurface->UpdateProperties(); m_pkWaterSurface->UpdateEffects(); // 创建 render step m_spRenderStep = NiNew NiDefaultClickRenderStep; // create water texture background render click m_spReflectBGRenderClick = NiNew NiViewRenderClick; //spWaterTexBGRenderClick->SetName("SkyBGClick"); m_spReflectBGRenderClick->AppendRenderView( m_spRTView ); m_spReflectBGRenderClick->SetRenderTargetGroup(m_spRTGroup0); m_spReflectBGRenderClick->SetClearAllBuffers(true); m_spReflectBGRenderClick->SetActive(true); m_spRenderStep->AppendRenderClick( m_spReflectBGRenderClick ); // create water texture render click m_spReflectTexRenderClick = NiNew NiViewRenderClick; //m_spWaterTexRenderClick->SetName("ReflectTexClick"); m_spReflectTexRenderClick->AppendRenderView(m_spWaterRenderView); m_spReflectTexRenderClick->SetRenderTargetGroup(m_spRTGroup0); m_spReflectTexRenderClick->SetClearAllBuffers(false); m_spReflectTexRenderClick->SetActive(true); m_spReflectTexRenderClick->SetPreProcessingCallbackFunc(_PreWaterTextureCallback, this); // 前回调函数 m_spReflectTexRenderClick->SetPostProcessingCallbackFunc(_PostWaterTextureCallback, this); // 后回调函数 m_spRenderStep->AppendRenderClick( m_spReflectTexRenderClick ); m_spRenderStep->SetActive( false ); //// 创建水面的 render view //CWaterRenderView* pkWaterBodyRenderView = NiNew CWaterRenderView(m_spMainCamera, m_spCuller, true); //pkWaterBodyRenderView->SetWaterBody(this); //// 创建主 render click.只渲染水面 //NiViewRenderClick* spWaterBodyRenderClick = NiNew NiViewRenderClick; //spWaterBodyRenderClick->AppendRenderView( pkWaterBodyRenderView ); //spWaterBodyRenderClick->SetClearAllBuffers(false); //m_spRenderStep->AppendRenderClick( spWaterBodyRenderClick ); m_bInitialized = true; // 测试 // m_spReflectTexRenderClick->SetActive(false); return true; } void CWaterBody::_CreateWaterBodyGeom() { // 创建雾表面几何体 NiPoint3* pkVertices = NiNew NiPoint3[4]; // 顶点位置 NiPoint3* pkNormals = NiNew NiPoint3[4]; // 法线 NiPoint2* pkTexCoord = NiNew NiPoint2[4]; // 纹理坐标 NiColorA* pkVertexClr = NiNew NiColorA[4]; // 顶点颜色 WORD* pConnect = NiAlloc( WORD, 6 ); // 顶点索引 这里用 new WORD[6] 会抱错 /* 1_2 |/| 0-3 */ pkVertices[0] = pkVertices[1] = pkVertices[2] = pkVertices[3] = NiPoint3(0.0f, 0.0f, 0.0f); pkVertices[1].y = 1.0f; pkVertices[2].x = 1.0f; pkVertices[2].y = 1.0f; pkVertices[3].x = 1.0f; pkNormals[0] = pkNormals[1] = pkNormals[2] = pkNormals[3] = NiPoint3(0.0f, 0.0f, 1.0f); //ZeroMemory(pkTexCoord, sizeof(NiPoint2)*4); pkTexCoord[0] = NiPoint2(0.0f, 1.0f); pkTexCoord[1] = NiPoint2(0.0f, 0.0f); pkTexCoord[2] = NiPoint2(1.0f, 0.0f); pkTexCoord[3] = NiPoint2(1.0f, 1.0f); pkVertexClr[0] = pkVertexClr[1] = pkVertexClr[2] = pkVertexClr[3] = NiColorA(1.0f, 1.0f, 1.0f, 1.0f); pConnect[0] = 0; pConnect[1] = 2; pConnect[2] = 1; pConnect[3] = 0; pConnect[4] = 3; pConnect[5] = 2; NiTriShapeDataPtr pData = NiNew NiTriShapeData( 4, pkVertices, pkNormals, pkVertexClr, pkTexCoord, 1, NiGeometryData::NBT_METHOD_NONE, 2, pConnect); m_pkWaterSurface = NiNew NiTriShape(pData); m_spRootScene->AttachChild(m_pkWaterSurface); } ////////////////////////////////////////////////////////////////////////// void CWaterBody::_CreateScreenFillingRenderViews() { // Create the render-to-texture object. m_spRTView = NiNew NiScreenFillingRenderView; m_spRTView->GetScreenFillingQuad().ApplyAndSetActiveMaterial( 0 ); m_pkRTViewTexProp = NiNew NiTexturingProperty; m_pkRTViewTexProp->SetBaseTexture( m_spTextureSky ); m_pkRTViewTexProp->SetBaseFilterMode( NiTexturingProperty::FILTER_NEAREST ); m_pkRTViewTexProp->SetApplyMode( NiTexturingProperty::APPLY_REPLACE ); m_spRTView->AttachProperty( m_pkRTViewTexProp ); NiZBufferProperty* pZProperty = NiNew NiZBufferProperty; pZProperty->SetZBufferWrite(false); pZProperty->SetZBufferTest(false); m_spRTView->AttachProperty( pZProperty ); m_spRTView->GetScreenFillingQuad().Update(0.0f); m_spRTView->GetScreenFillingQuad().UpdateEffects(); m_spRTView->GetScreenFillingQuad().UpdateProperties(); } // ///// 创建 bump map 函数作废 //bool CWaterBody::_CreateBumpMap(NiPoint2 kNumWaves) //{ // NiTexture::FormatPrefs kPrefs; // kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::TRUE_COLOR_32; // kPrefs.m_eMipMapped = NiTexture::FormatPrefs::NO; // // NiPixelData *pPixelData = NiNew NiPixelData( BUMPMAP_SIZE, BUMPMAP_SIZE, NiPixelFormat::RGBA32 ); // NiSourceTexture::SetDestroyAppDataFlag( false ); // m_spBumpMap = NiSourceTexture::Create( pPixelData ); // m_spBumpMap->SetStatic( false ); // NiSourceTexture::SetDestroyAppDataFlag( true ); // if ( !m_spBumpMap ) return false; // // int iNumPixPerWaveU = BUMPMAP_SIZE / kNumWaves.x; // int iNumPixPerWaveV = BUMPMAP_SIZE / kNumWaves.y; // // for ( int y = 0; y < BUMPMAP_SIZE; ++y ) // { // for ( int x = 0; x < BUMPMAP_SIZE; ++x ) // { // unsigned char *pPtr = ( *pPixelData )(x,y); // // float fx = (x%iNumPixPerWaveU)/(float)iNumPixPerWaveU - 0.5f; // float fy = (y%iNumPixPerWaveV)/(float)iNumPixPerWaveV - 0.2f; // // float r = sqrtf(fx*fx + fy*fy); // // char iDu, iDv; // iDu = (char)(64 * cosf(300.0f * r) * expf (-r*5.0f)); // iDu += (char)(32 * cosf(150.0f * (fx + fy))); // iDu += (char)(16 * cosf(140.0f*(fx*0.85f - fy))); // // iDv = (char)(64 * sinf(300.0f * r) * expf (-r*5.0f)); // iDv += (char)(32 * sinf(150.0f * (fx + fy))); // iDv += (char)(16 * sinf(140.0f * (fx*0.85f - fy))); // // pPtr[0] = iDu; // pPtr[1] = iDv; // //unsigned char cc = (sinf(((float)(x%iNumPixPerWaveU))/iNumPixPerWaveU*3.141593f)+1.0f)*0.5f*255; // //pPtr[0] = (sinf(((float)(x%iNumPixPerWaveU))/iNumPixPerWaveU*3.141593f)+1.0f)*0.5f*128+(sinf(((float)(y%iNumPixPerWaveV))/iNumPixPerWaveV*3.141593f)+1.0f)*0.5f*128; // ////cc = (sinf(((float)(y%iNumPixPerWaveV))/iNumPixPerWaveV*3.141593f)+1.0f)*0.5f*255; // //pPtr[1] = (sinf(((float)(x%iNumPixPerWaveU))/iNumPixPerWaveU*3.141593f)+1.0f)*0.5f*128+(sinf(((float)(y%iNumPixPerWaveV))/iNumPixPerWaveV*3.141593f)+1.0f)*0.5f*128; // pPtr[2] = 0; // pPtr[3] = 255; // } // } // // pPixelData->MarkAsChanged(); // // // //NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, NiDX9Renderer::GetRenderer()); // // // ////LPDIRECT3DBASETEXTURE9 PrepareTextureForRendering(NiTexture* pNewTexIm, bool &bChanged, bool &bMipmap, bool &bNonPow2) // //// This function takes the NiTexture that is passed in and ensures that it is ready to be rendered. // //// It returns a pointer to the DX texture that can be used with a NiD3DRenderState::SetTexture call, // //// and three Boolean values indicating whether the texture needs to be updated, whether the texture // //// contains mipmaps, and whether it has one or both dimensions that are not round powers of two. // // //bool bChanged = true; // //bool bMipmap = false; // //bool bNonPow2 = false; // //LPDIRECT3DBASETEXTURE9 pD3D9Tex = pkDX9Renderer->GetTextureManager()->PrepareTextureForRendering(m_spBumpMap, bChanged, bMipmap, bNonPow2); // // // //HRESULT hr = D3DXSaveTextureToFileA("e:/testTexture1.dds",D3DXIFF_DDS,pD3D9Tex,NULL); // //if (FAILED(hr)) // //{ // // return true; // //} // // return true; //} bool CWaterBody::_PreWaterTextureCallback( NiRenderClick* pkCurrentRenderClick, void* pvCallbackData ) { CWaterBody* pWaterbody = static_cast(pvCallbackData); NiCamera* pkCamera = pWaterbody->GetMainCamera(); pWaterbody->SetMainCamera(pkCamera); // 保存摄像机参数 NiPoint3 kCamPos = pkCamera->GetTranslate(); NiPoint3 kDirection = pkCamera->GetWorldDirection(); pWaterbody->SaveCamParam(kCamPos, kDirection); // 根据水面镜像摄像机位置 float fWaterZ = pWaterbody->GetPosition().z; kCamPos.z = fWaterZ-(kCamPos.z-fWaterZ); pkCamera->SetTranslate(kCamPos); pkCamera->Update(0.0f); // 镜像摄像机方向 kDirection.z = (-kDirection.z); pkCamera->LookAtWorldPoint(kCamPos+kDirection, NiPoint3::UNIT_Z); pkCamera->Update(0.0f); //NiSpeedTreeComponent::GetManager()->SetCurrentCamera(pkCamera); //NiSpeedTreeComponent::GetManager()->Update(0.0f); pWaterbody->SetMainCamera(pkCamera); pWaterbody->SetWaterClipPlane(true); // 设置万摄像机后再设置 clip plane //NiStencilProperty* pStencilProp = NiRenderer::GetRenderer()->GetPropertyState()->GetStencil(); //pStencilProp->SetDrawMode(NiStencilProperty::DRAW_BOTH); return true; } bool CWaterBody::_PostWaterTextureCallback( NiRenderClick* pkCurrentRenderClick, void* pvCallbackData ) { // 渲染 speed tree CWaterBody* pWaterbody = static_cast(pvCallbackData); NiCamera* pkCamera = pWaterbody->GetMainCamera(); NiPoint3 kCamPos ; NiPoint3 kDirection ; pWaterbody->RetrieveCamParam(kCamPos, kDirection); // 恢复摄像机位置 pkCamera->SetTranslate(kCamPos); pkCamera->Update(0.0f); // 恢复摄像机方向 pkCamera->LookAtWorldPoint(kCamPos+kDirection, NiPoint3::UNIT_Z); pkCamera->Update(0.0f); //NiSpeedTreeComponent::GetManager()->SetCurrentCamera(pkCamera); //NiSpeedTreeComponent::GetManager()->Update(0.0f); pWaterbody->SetMainCamera(pkCamera); pWaterbody->SetWaterClipPlane(false); return true; } void CWaterBody::BuildVisibleSet( NiCamera * pCamera, NiCullingProcess* pCullingProcess ) { // 判断本水体是否被加入到渲染集中 unsigned int iNumGeoBefore = pCullingProcess->GetVisibleSet()->GetCount(); NiCullScene(pCamera, m_spRootScene, *pCullingProcess, *(pCullingProcess->GetVisibleSet()), false); m_bInVisableArray = (pCullingProcess->GetVisibleSet()->GetCount() > iNumGeoBefore); } NiCamera* CWaterBody::GetMainCamera() { if (NULL != m_spWaterRenderView) { return m_spWaterRenderView->GetCamera(); } else { return NULL; } } void CWaterBody::SetMainCamera(NiCamera* pCamera) { if (NULL!=m_spWaterRenderView && NULL!=NiRenderer::GetRenderer()) { m_spWaterRenderView->SetAlwaysUseCameraViewport(false); m_spWaterRenderView->SetCamera(pCamera); NiRenderer::GetRenderer()->SetCameraData(pCamera); } } void CWaterBody::SetWaterClipPlane(bool bSet) { NiDX9Renderer* pkDX9Renderer = NiDynamicCast(NiDX9Renderer, NiDX9Renderer::GetRenderer()); const LPDIRECT3DDEVICE9 pD3DDevice = pkDX9Renderer->GetD3DDevice(); static const float CLIP_PLANE_OFFSET = 0.2f; if (bSet) { D3DXPLANE waterPlane(0, 0, 1, -(m_kPosition.z-CLIP_PLANE_OFFSET)); D3DXMATRIX matView, matProj, matProjView, matInvTransProjView; matProj = pkDX9Renderer->GetD3DProj(); matView = pkDX9Renderer->GetD3DView(); D3DXMatrixMultiply(&matProjView, &matView,&matProj ); D3DXMatrixInverse(&matInvTransProjView, NULL, &matProjView); D3DXMatrixTranspose(&matInvTransProjView, &matInvTransProjView); D3DXPlaneTransform(&waterPlane, &waterPlane, &matInvTransProjView); // 使用 shader 时,这个平面必须在 clip space HRESULT hr = pD3DDevice->SetClipPlane(0, waterPlane); pD3DDevice->SetRenderState(D3DRS_CLIPPING, true); pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0); } else { pD3DDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, FALSE); } } void CWaterBody::SetMainRenderView(CWaterRenderViewPtr pMainRenderView) { if (m_bInitialized && pMainRenderView != NULL) { m_spWaterRenderView = pMainRenderView; m_spReflectTexRenderClick->RemoveAllRenderViews(); m_spReflectTexRenderClick->AppendRenderView(m_spWaterRenderView); } } void CWaterBody::SaveCamParam(const NiPoint3& kPos, const NiPoint3& kDir) { m_kSaveCameraPos = kPos; m_kSaveCameraDir = kDir; } void CWaterBody::RetrieveCamParam(NiPoint3& kPos, NiPoint3& kDir) { kPos = m_kSaveCameraPos; kDir = m_kSaveCameraDir; } /// 更新 void CWaterBody::Update(float fTotalTime ) { if ( m_spRenderStep && m_spRenderStep->GetActive()) { float r = 0.002f; float fScale = 5.0f; m_kBumpMat.m_fX = r * cosf(fTotalTime * fScale); m_kBumpMat.m_fY = -r * sinf(fTotalTime * fScale); m_kBumpMat.m_fZ = r * sinf(fTotalTime * fScale); m_kBumpMat.m_fW = r * cosf(fTotalTime * fScale); NiFloatsExtraData * pExtraData = (NiFloatsExtraData*)m_pkWaterSurface->GetExtraData("BumpMatrix"); pExtraData->SetArray(4, (float *)&m_kBumpMat.m_fX); pExtraData = (NiFloatsExtraData*)m_pkWaterSurface->GetExtraData("BumpMapOffset"); pExtraData->SetArray(2, (float *)&(m_kUVSpeed*fTotalTime*0.01f)); //m_spRootScene->Update(fElapsedTime); ////m_spRootScene->Update(0.0f); //m_spRootScene->UpdateEffects(); //m_spRootScene->UpdateProperties(); } } void CWaterBody::Enable() { // 打开实时反射 m_spReflectTexRenderClick->SetActive(true); } void CWaterBody::Disable() { // 关闭实时反射 m_spReflectTexRenderClick->SetActive(false); } void CWaterBody::RenderReflectTexture(NiEntityRenderingContext* pkRenderingContext) { if (!m_bInVisableArray || !m_bInitialized) { return; } // Backup current render target group. const NiRenderTargetGroup* pkCurRenderTarget = pkRenderingContext ->m_pkRenderer->GetCurrentRenderTargetGroup(); if ( !pkCurRenderTarget ) return; //NIASSERT(pkCurRenderTarget != NULL); pkRenderingContext->m_pkRenderer->EndUsingRenderTargetGroup(); m_spRenderStep->SetActive(true); m_spWaterRenderView->SetAlwaysUseCameraViewport(false); m_spWaterRenderView->SetCamera(pkRenderingContext->m_pkCamera); m_spRenderStep->Render(); // Restore previous render target group. if (pkRenderingContext->m_pkRenderer->IsRenderTargetGroupActive()) { pkRenderingContext->m_pkRenderer->EndUsingRenderTargetGroup(); } if ( pkCurRenderTarget ) { pkRenderingContext->m_pkRenderer->BeginUsingRenderTargetGroup( (NiRenderTargetGroup*) pkCurRenderTarget, NiRenderer::CLEAR_NONE); } //pkRenderingContext->m_pkRenderer->Set //pkRenderingContext->m_pkCamera->vie } //void CWaterBody::RenderSpeedTree() //{ // NiRenderer* pkRenderer = NiRenderer::GetRenderer(); // NiSpeedTreeManager* pkTreeMgr = NiSpeedTreeComponent::GetManager(); // //CWaterManager::GetInstance()->GetMainWaterRenderView()- //}