What I was not aware of was that Hoppe also wrote an absolutely fantastic article with Arul Asirvatham which discussed this same terrain rendering with a very heavy emphasis on practical use of the GPU using shader model 3.0 (namely, the use of vertex textures). After skimming this GPU Gems 2 article I was firmly convinced that I need to implement the algorithm as soon as I could get around to it. So, over the course of the last couple days I've read over the GPU Gems 2 article along with the original whitepaper upon which it was based several times each and also skimmed over the basic implementation done by FilouGK and I think I have come to pretty decent understanding of the algorithm.
One of the first things I usually do before undertaking any sort of non-trivial programming is to "sketch" (ie, write the code for) the class definition first. This is clearly a revolutionary first step, so take a moment to regain your composure at my genius.
But, yeah, I generally find that to be the only prerequisite for me when starting any project. I don't, as a rule, draw an excessive amount of pictures and diagram, I don't write pseudocode to detail the routines that I will, then, actually code, and I don't draw up unnecessary UML diagrams to detail how various data structures will interact with one another. Once I can look at a class definition and think "Yup," I just start coding and don't stop until I get something displaying on the screen which is, more or less, what I'm aiming for. Of course, that "first step" of getting things on the screen is far from a final product -- I program in a very incremental sort of process.
So, I apologize for the excessively dry nature of this dev journal entry. It has to do with a combination of my ridiculously tired state coupled with the fact that this is a journal entry was meant to lay the ground work for this terrain implementation which, I hope, will prove a decent tutorial on the topic as I go on. Anyhoo, here's the class definition as I have it so far.
class CTerrainNode : public ISceneNode{public: ~CTerrainNode( ); virtual HRESULT Create( CScene *pScene ); virtual void Release( ); HRESULT Init( CScene *pScene ); virtual HRESULT Update( float fTimestep ); virtual HRESULT Prerender( CScene *pScene ); virtual HRESULT Render( CScene *pScene ); virtual HRESULT Postrender( CScene *pScene ); void SetWorldViewProjMatrix( D3DXMATRIX matrixWorld );protected: CTerrainNode( );private: struct Clipmap { CTextureWrapper* m_pHeightMap; //One Channel FP Height Data (DXGI_FORMAT_R32_FLOAT) CTextureWrapper* m_pNormalMap; //Four Channel Texture (DXGI_FORMAT_R8G8B8A8_UNORM) ID3D10EffectShaderResourceVariable* m_pHeightTextureVar; ID3D10EffectShaderResourceVariable* m_pNormalTextureVar; };private: //Algorithm Data. Clipmap* m_pClipmaps; D3DXVECTOR3 m_v3ViewerPos; //Viewer position (Vx, Vz needed for block updates - Vy for active_region calcs). unsigned long m_ulLevels; //L unsigned long m_ulGridSize; //n (2^k - 1). //M x M Block Geometry. unsigned long m_ulBlockVertexRes; //m (( n + 1 )/4) unsigned long m_ulBlockNumVertices; unsigned long m_ulBlockNumTriangles; //M x 3 Block Geometry. unsigned long m_ulRingNumVertices; unsigned long m_ulRingNumTriangles; //( 2m + 1 ) x 2 Trim Geometry. unsigned long m_ulTrimNumVertices; unsigned long m_ulTrimNumTriangles; //Outer Border of Degenerate Triangles. unsigned long m_ulDTNumVertices; unsigned long m_ulDTNumTriangles; //Shader Variables //Frame. D3DXMATRIX m_matWorldViewProj; D3DXVECTOR3 m_v3LightDir; //Block. (Per-Clipmap?) D3DXVECTOR4 m_v4FineTextureOrigin; D3DXVECTOR2 m_v2AlphaOffset; D3DXVECTOR4 m_v4ScaleFactor; float m_fZScaleFactor; float m_fOneOverWidth; //Direct3D Data. CInputDescWrapper* m_pInputLayout; CVertexBufferWrapper* m_pBlockVB; //m x m Block. CVertexBufferWrapper* m_pRingVB[TERRAIN_LRING_COUNT]; //m x 3 Ring Fix-Up. CVertexBufferWrapper* m_pTrimVB; //(2m + 1)*2 Interior Trim. CVertexBufferWrapper* m_pDegenerateTriVB; //Outer Degenerate Triangles. CIndexBufferWrapper* m_pBlockIB; CIndexBufferWrapper* m_pRingIB; CTextureWrapper* m_pDiffuseTexture; ID3D10Effect* m_pEffect; ID3D10EffectTechnique* m_pRenderTechnique; ID3D10EffectTechnique* m_pUpsampleTechnique; ID3D10EffectTechnique* m_pNormalCalcTechnique; ID3D10EffectMatrixVariable* m_pViewVariable; ID3D10EffectMatrixVariable* m_pProjectionVariable; //Vertex/Pixel Shader Handles. ID3D10EffectMatrixVariable* m_pWorldViewProjVar; //matrix. ID3D10EffectVectorVariable* m_pViewerPositionVar; //float2. ID3D10EffectVectorVariable* m_pLightDirVar; //float3. ID3D10EffectVectorVariable* m_pFineTextureOriginVar; //float4. ID3D10EffectVectorVariable* m_pAlphaOffsetVar; //float2. ID3D10EffectVectorVariable* m_pScaleFactorVar; //float4. ID3D10EffectScalarVariable* m_pZScaleFactorVar; //float. ID3D10EffectScalarVariable* m_pOneOverWidthVar; //float. //Constants static const LPCTSTR TERRAINNODE_INPUTLAYOUTWRAPPER_NAME; static const LPCTSTR TERRAINNODE_BLOCK_VBWRAPPER_NAME; static const LPCTSTR TERRAINNODE_RING_VBWRAPPER_NAME; static const LPCTSTR TERRAINNODE_TRIM_VBWRAPPER_NAME; static const LPCTSTR TERRAINNODE_DEGENTRI_VBWRAPPER_NAME; static const LPCTSTR TERRAINNODE_BLOCK_IBWRAPPER_NAME; static const LPCTSTR TERRAINNODE_RING_IBWRAPPER_NAME; static const LPCTSTR TERRAINNODE_EFFECT_FILENAME; static const LPCSTR TERRAINNODE_EFFECT_SHADERPROFILE; //Algorithm constants. static const unsigned long TERRAINNODE_GRIDSIZE_DEFAULT;friend class CSceneNodeManager;};
I probably won't be able to write another entry until Sunday or Monday, as I'm moving into a new apartment on Friday, so I'll pick this up again once I get settled.