#include "StdAfx.h" #ifndef CODE_INGAME #include "AOPerVertexShadowGeneratorGPU.h" #include "Terrain.h" #include "TerrainModifier.h" using namespace SceneCore; CAOPerVertexShadowGeneratorGPU::CAOPerVertexShadowGeneratorGPU(CTerrain* pkTerrain) : m_pkTerrain(pkTerrain), m_kDiskGenerator(pkTerrain) { //if (pkTerrain != NULL) //{ // m_kDiskGenerator.GenerateDisk(pkTerrain); //} } CAOPerVertexShadowGeneratorGPU::~CAOPerVertexShadowGeneratorGPU(void) { } /// 添加投射阴影的物件,利用该物件产生 AODisk void CAOPerVertexShadowGeneratorGPU::AddShadowEmitter(NiAVObjectPtr pkAVObj) { if (pkAVObj != NULL) { m_kDiskGenerator.RecursiveFindGenerateDisk(pkAVObj); } } /// 产生地形阴影 void CAOPerVertexShadowGeneratorGPU::GenerateTerrainShadow() { /************************************************************************/ /* CAODiskGenerator 重新写过,所以暂时注释本函数. */ /************************************************************************/ /* // 1. 创建存放 disk info 的纹理 NiTexture::FormatPrefs kPrefs; kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::FLOAT_COLOR_128; kPrefs.m_eMipMapped = NiTexture::FormatPrefs::NO; NiPixelData *pPosPixelData = NiNew NiPixelData( TEXTURE_SIZE, TEXTURE_SIZE, NiPixelFormat::RGBA128); NiPixelData *pNormalPixelData = NiNew NiPixelData( TEXTURE_SIZE, TEXTURE_SIZE, NiPixelFormat::RGBA128); ZeroMemory((*pPosPixelData)(0,0), TEXTURE_SIZE*TEXTURE_SIZE*sizeof(float)*4); ZeroMemory((*pNormalPixelData)(0,0), TEXTURE_SIZE*TEXTURE_SIZE*sizeof(float)*4); NiSourceTexture::SetDestroyAppDataFlag( false ); NiSourceTexturePtr pkPositionTexture = NiSourceTexture::Create( pPosPixelData ); NiSourceTexturePtr pkNormalTexture = NiSourceTexture::Create( pNormalPixelData ); pkPositionTexture->SetStatic( false ); pkNormalTexture->SetStatic( false ); NiSourceTexture::SetDestroyAppDataFlag( true ); if ( !pkPositionTexture || !pkNormalTexture ) { return; } // 2. 遍历所有 disk, 将所有 disk 的位置,法线,面积 拷贝到纹理上. int iIdx = 0; list::iterator iter = m_kDiskGenerator.m_TerrainDiskList.begin(); while (iter != m_kDiskGenerator.m_TerrainDiskList.end()) { tAODisk& disk = *iter; int iX = iIdx%TEXTURE_SIZE; int iY = iIdx/TEXTURE_SIZE; float* pfPos = (float*)((*pPosPixelData)(iX, iY)); (*pfPos++) = disk.kPosition.x; (*pfPos++) = disk.kPosition.y; (*pfPos++) = disk.kPosition.z; (*pfPos) = disk.fArea/3.1416f; //(*pfPos) = 0.2f; //if (iIdx == 0) (*pfPos) = 0.1; float* pfNormal = (float*)((*pNormalPixelData)(iX, iY)); (*pfNormal++) = disk.kNormal.x; (*pfNormal++) = disk.kNormal.y; (*pfNormal++) = disk.kNormal.z; (*pfNormal) = 1.0f; iter++; iIdx++; } pPosPixelData->MarkAsChanged(); pNormalPixelData->MarkAsChanged(); //SaveTextureToDDS(pkPositionTexture, "e:\\pos.dds"); //SaveTextureToDDS(pkNormalTexture, "e:\\normal.dds"); // 3. 在blend texture 的每个像素位置计算相对所有 disk 的遮挡关系,输出到 texture 中 // 3.1 将地形的 NiTriShape 做一份拷贝, 赋以 AOMaterial CTerrain::stChunk* pChunks = m_pkTerrain->GetChunks(); int iNumChunksX = m_pkTerrain->GetChunkNumX(); int iNumChunksY = m_pkTerrain->GetChunkNumY(); NiTPointerList terrainGeometryList; // 地形 geometry 列表 NiPoint2 kTerrainSize(iNumChunksX*GRIDINCHUNK, iNumChunksY*GRIDINCHUNK); NiPoint2 kTexelSize(1.0f/iNumChunksX*BLENDTEX_SIZE, 1.0f/iNumChunksY*BLENDTEX_SIZE); //NiFloatsExtraData *pkEDTerrainSize = NiNew NiFloatsExtraData( 2, (float *)&kTerrainSize.x); //NiFloatsExtraData *pkEDTexelSize = NiNew NiFloatsExtraData( 2, (float *)&kTexelSize.x); NiFloatExtraData *pkEDNumDisks = NiNew NiFloatExtraData((float)iIdx); NiTexturingProperty* pkTexProp = NiNew NiTexturingProperty(); NiTexturingProperty::ShaderMap* pkMap0 = NiNew NiTexturingProperty::ShaderMap(pkPositionTexture, 0, NiTexturingProperty::WRAP_S_WRAP_T, NiTexturingProperty::FILTER_NEAREST, 0); pkTexProp->SetShaderMap(0, pkMap0); NiTexturingProperty::ShaderMap* pkMap1 = NiNew NiTexturingProperty::ShaderMap(pkPositionTexture, 1, NiTexturingProperty::WRAP_S_WRAP_T, NiTexturingProperty::FILTER_NEAREST, 1); pkTexProp->SetShaderMap(1, pkMap1); NiMaterialPtr pkAOMaterial = NiSingleShaderMaterial::Create("AmbientOcclusion"); NIASSERT(pkAOMaterial); for (int i=0; iGetModelData())); pkTriShape->ApplyAndSetActiveMaterial(pkAOMaterial); //pkTriShape->AddExtraData("TerrainSize", pkEDTerrainSize); //pkTriShape->AddExtraData("TexelSize", pkEDTexelSize); pkTriShape->AddExtraData("NumDisks", pkEDNumDisks); pkTriShape->AttachProperty(pkTexProp); pkTriShape->Update(0.0f); pkTriShape->UpdateProperties(); pkTriShape->UpdateEffects(); terrainGeometryList.AddTail(pkTriShape); } // 3.2 设置摄像机,使正好可以覆盖整个地形并且正交 NiCamera kCamera; //NiFrustum kFrustum(-iNumChunksX*GRIDINCHUNK/2, iNumChunksX*GRIDINCHUNK/2, // iNumChunksY*GRIDINCHUNK/2, -iNumChunksY*GRIDINCHUNK/2, 0.1f, 1000.0f, true); //kCamera.SetTranslate(iNumChunksX*GRIDINCHUNK/2, iNumChunksY*GRIDINCHUNK/2, 500); //kCamera.LookAtWorldPoint(NiPoint3(iNumChunksX*GRIDINCHUNK/2, iNumChunksY*GRIDINCHUNK/2, -1000.0f), NiPoint3(0, 1, 0)); kCamera.SetTranslate(0, 0, 500); kCamera.LookAtWorldPoint(NiPoint3(0, 0, -1000.0f), NiPoint3(0, 1, 0)); kCamera.Update(0.0f); NiFrustum kFrustum(0, iNumChunksX*GRIDINCHUNK, iNumChunksY*GRIDINCHUNK, 0, 0.1f, 1000.0f, true); kCamera.SetViewFrustum(kFrustum); kCamera.Update(0.0f); NiRenderer* pkRenderer = NiRenderer::GetRenderer(); // 3.3 生成 RTG kPrefs.m_ePixelLayout = NiTexture::FormatPrefs::TRUE_COLOR_32; NiRenderedTexturePtr pkRTTexture = NiRenderedTexture::Create(iNumChunksX*BLENDTEX_SIZE, iNumChunksY*BLENDTEX_SIZE, pkRenderer, kPrefs, Ni2DBuffer::MULTISAMPLE_NONE); NiRenderTargetGroupPtr pkRTG = NiRenderTargetGroup::Create(pkRTTexture->GetBuffer(), pkRenderer, true, true); NiRenderTargetGroup* pkCurrentRTG = NULL; // 3.4 渲染地形到 RTG // back up current RTG if (pkRenderer->IsRenderTargetGroupActive()) { pkCurrentRTG = (NiRenderTargetGroup*)(pkRenderer->GetCurrentRenderTargetGroup()); pkRenderer->EndUsingRenderTargetGroup(); } pkRenderer->BeginOffScreenFrame(); pkRenderer->BeginUsingRenderTargetGroup(pkRTG, NiRenderer::CLEAR_ALL); pkRenderer->SetCameraData(&kCamera); NiVisibleArray kVisibleArray; NiCullingProcess kCullingProcess(&kVisibleArray); NiTListIterator it = terrainGeometryList.GetHeadPos(); while (it) { NiCullScene(&kCamera, (terrainGeometryList.GetNext(it)), kCullingProcess, kVisibleArray, false); } UINT uiCount = NiDrawVisibleArray(&kCamera, kVisibleArray); pkRenderer->EndUsingRenderTargetGroup(); pkRenderer->EndOffScreenFrame(); CTerrainModifier::ApplyShadowTexture(m_pkTerrain, NiDynamicCast(NiTexture, pkRTTexture)); SaveTextureToDDS(pkRTTexture, "e:\\test.dds"); if (pkCurrentRTG != NULL) { pkRenderer->BeginUsingRenderTargetGroup(pkCurrentRTG, NiRenderer::CLEAR_NONE); } // 4. 将上个 pass 的 texture 像素拷贝到 alpha channel of blend texture. */ } #endif