www.pudn.com > Samples-latest.zip > CubeMapFunction.h
// Evaluates a complex light environment by a given CubeMap templatestruct TCubeMapFunction : public ZFXMath::SphericalHarmonics::TSphericalFunction< PrecisionType, FuncValueType > { typedef ZFXMath::SphericalHarmonics::TSample Sample; struct TLVertex { float x, y, z, rhw; DWORD color; // for 32 Byte Stride float u, v, w; // Lookup for Cube Map }; TCubeMapFunction( LPDIRECT3DDEVICE9 pD3DDevice, int numSamples ) { m_pD3DDevice = pD3DDevice; m_NumSamples = numSamples; m_FuncValue = new FuncValueType[m_NumSamples * m_NumSamples * 2]; // Steps along the sphere PrecisionType du = PrecisionType( ZFXMath::PI / m_NumSamples ); PrecisionType dv = PrecisionType( 2 * ZFXMath::PI / (m_NumSamples * 2) ); m_Theta = 1 / du; m_Phi = 1 / dv; m_Vertex = new TLVertex[m_NumSamples * m_NumSamples * 2]; // each pixel in the render target becomes a point // on a sphere to lookup the cubemap PrecisionType v = 0; for ( int m = 0; m < m_NumSamples * 2; m++ ) { PrecisionType u = 0; for ( int n = 0; n < m_NumSamples; n++ ) { // compute spherical coordinates (for texture lookup) Sample s( u, v ); m_Vertex[ m * m_NumSamples + n ].x = float( n ); m_Vertex[ m * m_NumSamples + n ].y = float( m ); m_Vertex[ m * m_NumSamples + n ].z = 0.0f; m_Vertex[ m * m_NumSamples + n ].rhw = 1.0f; m_Vertex[ m * m_NumSamples + n ].color = 0; //n + (m << 16); m_Vertex[ m * m_NumSamples + n ].u = s.x; m_Vertex[ m * m_NumSamples + n ].v = s.y; m_Vertex[ m * m_NumSamples + n ].w = s.z; u += du; } v += dv; } m_pD3DDevice->CreateRenderTarget( numSamples, numSamples * 2, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, true, &m_pSphericalRT, NULL ); m_pD3DDevice->CreateOffscreenPlainSurface( numSamples, numSamples * 2, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &m_pSphericalSurface, NULL ); } ~TCubeMapFunction() { m_pSphericalRT->Release(); m_pSphericalSurface->Release(); // clean up delete[] m_Vertex; delete[] m_FuncValue; } void EvaluateCubeMap( LPDIRECT3DCUBETEXTURE9 pCubeMap ) { LPDIRECT3DSURFACE9 pBackBuffer = NULL; LPDIRECT3DSURFACE9 pDepthStencil = NULL; m_pD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer ); m_pD3DDevice->GetDepthStencilSurface( &pDepthStencil ); m_pD3DDevice->SetRenderTarget( 0, m_pSphericalRT ); m_pD3DDevice->SetDepthStencilSurface( NULL ); m_pD3DDevice->SetTexture( 0, pCubeMap ); m_pD3DDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0) ); m_pD3DDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); m_pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); m_pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); m_pD3DDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 ); m_pD3DDevice->BeginScene(); //------------------------------ // Rendering int primitiveCount = 65535; int primitiveIndex = 0; while ( m_NumSamples * m_NumSamples * 2 - primitiveIndex ) { primitiveCount = ZFXMath::Min( ( m_NumSamples * m_NumSamples * 2 - primitiveIndex ), primitiveCount ); m_pD3DDevice->DrawPrimitiveUP( D3DPT_POINTLIST, primitiveCount, &m_Vertex[primitiveIndex], 32 ); primitiveIndex += primitiveCount; } //------------------------------ m_pD3DDevice->EndScene(); m_pD3DDevice->SetRenderTarget( 0, pBackBuffer ); m_pD3DDevice->SetDepthStencilSurface( pDepthStencil ); pBackBuffer->Release(); pDepthStencil->Release(); m_pD3DDevice->GetRenderTargetData( m_pSphericalRT, m_pSphericalSurface ); std::ostringstream oss; std::string str; oss << "C:/sphere" << timeGetTime() << ".bmp"; str = oss.str(); //D3DXSaveSurfaceToFile( str.c_str(), D3DXIFF_BMP, m_pSphericalSurface, NULL, NULL ); // put the created spherical map into the phi-theta array D3DLOCKED_RECT LockedRect; m_pSphericalSurface->LockRect( &LockedRect, NULL, D3DLOCK_READONLY ); const int SURFACE_BYTE_DEPTH = 4; ARGB* pColor = (ARGB*)LockedRect.pBits; for ( int m = 0; m < m_NumSamples * 2; m++ ) { for ( int n = 0; n < m_NumSamples; n++ ) { ARGB& Color = pColor[ ( LockedRect.Pitch / SURFACE_BYTE_DEPTH ) * m + n ]; m_FuncValue[ m * m_NumSamples + n ] = FuncValueType( Color.R, Color.G, Color.B ) / 255.0f ; } } m_pSphericalSurface->UnlockRect(); } FuncValueType EvalFunction(const ZFXMath::SphericalHarmonics::TSample & s) const { FuncValueType ret; // 00 10 // 01 11 PrecisionType u = PrecisionType( ZFXMath::Min( s.theta, PrecisionType(PI) ) * m_Theta ); PrecisionType v = PrecisionType( ZFXMath::Min( s.phi, PrecisionType(2 * PI) ) * m_Phi ); int pX0 = ZFXMath::Min( int( u ), m_NumSamples - 1 ); int pY0 = ZFXMath::Min( int( v ), m_NumSamples * 2 - 1 ); u -= pX0; v -= pY0; int pX1 = ZFXMath::Min( pX0 + 1, m_NumSamples - 1 ); int pY1 = ZFXMath::Min( pY0 + 1, m_NumSamples * 2 - 1 ); FuncValueType& p00 = m_FuncValue[ pY0 * m_NumSamples + pX0 ]; FuncValueType& p10 = m_FuncValue[ pY0 * m_NumSamples + pX1 ]; FuncValueType& p01 = m_FuncValue[ pY1 * m_NumSamples + pX0 ]; FuncValueType& p11 = m_FuncValue[ pY1 * m_NumSamples + pX1 ]; ret = ZFXMath::Interpolate( ZFXMath::Interpolate( p00, p10, u ), ZFXMath::Interpolate( p01, p11, u ), v ); return ret; } private: int m_NumSamples; PrecisionType m_Theta; PrecisionType m_Phi; FuncValueType* m_FuncValue; TLVertex* m_Vertex; LPDIRECT3DDEVICE9 m_pD3DDevice; LPDIRECT3DSURFACE9 m_pSphericalRT; LPDIRECT3DSURFACE9 m_pSphericalSurface; };