游戏架构其九:光线投射和天空 { Raycast and Sky }

来源:互联网 发布:mysql 导入employees 编辑:程序博客网 时间:2024/04/30 18:21

光线和天空能够大大增强游戏的画面效果,以下是实现:

1. 光线效果 Raycast

#pragma once//========================================================================// Raycast.h - implements a raycast into the rendered scene//========================================================================#include "Geometry.h"typedef unsigned int  DWORD;typedef unsigned short WORD;typedef unsigned char  BYTE;typedef unsigned int  ActorId;typedef unsigned int  GameViewId;typedef D3DXCOLOR     Color;typedef float         FLOAT;typedef unsigned int  UINT;#ifdef   UNICODEtypedef wchar_t       TCHAR;#elsetypedef unsigned char TCHAR;#endiftypedef unsigned char CHAR;typedef unsigned wchar_t WCHAR;enum HRESULT{    E_INVALIDARG,    E_FAIL,    S_OK,};class Intersection{public:    FLOAT m_fDist;                  // distance from ray origin to intersectionDWORD m_dwFace;// the face index of the intersectionFLOAT m_fBary1, m_fBary2;// Barycentric质心 coordinates of the intersection    FLOAT m_tu, m_tv;               // texture coords of intersectionActorId m_actorId;// Which actor was intersected if there was oneVec3 m_worldLoc;// world location of intersectionVec3 m_actorLoc;// actor local coordinates of intersectionVec3 m_normal;// normal of intersectionbool const operator <(Intersection const &other) { return m_fDist < other.m_fDist; }};template <class T>void InitIntersection(Intersection &intersection, DWORD faceIndex, FLOAT dist, FLOAT u, FLOAT v, ActorId actorId, WORD* pIndices, T* pVertices, const Mat4x4 &matWorld);typedef std::vector<Intersection> IntersectionArray;class CDXUTSDKMesh;class RayCast{protected:LPDIRECT3DVERTEXBUFFER9     m_pVB; public:RayCast(Point point, DWORD maxIntersections = 16);DWORD m_MaxIntersections;DWORD m_NumIntersections;bool m_bUseD3DXIntersect;      // Whether to use D3DXIntersectbool m_bAllHits;// Whether to just get the first "hit" or all "hits"Point m_Point;D3DXVECTOR3 m_vPickRayDir;    D3DXVECTOR3 m_vPickRayOrig;IntersectionArray m_IntersectionArray;HRESULT Pick(Scene *pScene, ActorId actorId, ID3DXMesh *pMesh);HRESULT Pick(Scene *pScene, ActorId actorId, CDXUTSDKMesh *pMesh);HRESULT Pick(Scene *pScene, ActorId actorId, LPDIRECT3DVERTEXBUFFER9 pVerts, LPDIRECT3DINDEXBUFFER9 pIndices, DWORD numPolys);HRESULT Pick(Scene *pScene, ActorId actorId, LPDIRECT3DVERTEXBUFFER9 pVerts, DWORD numPolys);void Sort();};
//========================================================================// Raycast.cpp - implements a raycast into the rendered scene//========================================================================#include "GameCodeStd.h"#include "GameCode.h"#include "Geometry.h"#include "Raycast.h"#include "SceneNodes.h"template <class T>void InitIntersection(Intersection &intersection, DWORD faceIndex, FLOAT dist, FLOAT u, FLOAT v, ActorId actorId, WORD* pIndices, T* pVertices, const Mat4x4 &matWorld){intersection.m_dwFace = faceIndex;intersection.m_fDist = dist;intersection.m_fBary1 = u;    intersection.m_fBary2 = v;T *v0 = &pVertices[pIndices[3 * faceIndex + 0]];T *v1 = &pVertices[pIndices[3 * faceIndex + 1]];T *v2 = &pVertices[pIndices[3 * faceIndex + 2]];    // If all you want is the vertices hit, then you are done.  In this sample, we    // want to show how to infer texture coordinates as well, using the BaryCentric    // coordinates supplied by D3DXIntersect    FLOAT dtu1 = v1->tu - v0->tu;    FLOAT dtu2 = v2->tu - v0->tu;    FLOAT dtv1 = v1->tv - v0->tv;    FLOAT dtv2 = v2->tv - v0->tv;    intersection.m_tu = v0->tu + intersection.m_fBary1 * dtu1 + intersection.m_fBary2 * dtu2;    intersection.m_tv = v0->tv + intersection.m_fBary1 * dtv1 + intersection.m_fBary2 * dtv2;Vec3 a = v0->position - v1->position;Vec3 b = v2->position - v1->position;Vec3 cross = a.Cross(b);cross /= cross.Length();Vec3 actorLoc = BarycentricToVec3(v0->position, v1->position, v2->position, intersection.m_fBary1, intersection.m_fBary2);intersection.m_actorLoc = actorLoc;intersection.m_worldLoc = matWorld.Xform(actorLoc);intersection.m_actorId = actorId;intersection.m_normal = cross;}RayCast::RayCast(Point point, DWORD maxIntersections){m_MaxIntersections = maxIntersections;m_IntersectionArray.reserve(m_MaxIntersections);m_bUseD3DXIntersect = true;m_bAllHits = true;m_NumIntersections = 0;m_Point = point;}HRESULT RayCast::Pick(Scene *pScene, ActorId actorId, ID3DXMesh *pMesh){if (!m_bAllHits && m_NumIntersections > 0)return S_OK;HRESULT hr;    IDirect3DDevice9* pD3Device = DXUTGetD3D9Device();// Get the inverse view matrix    const Mat4x4 matView = pScene->GetCamera()->GetView();    const Mat4x4 matWorld = pScene->GetTopMatrix();const Mat4x4 proj = pScene->GetCamera()->GetProjection();    // Compute the vector of the Pick ray in screen space    D3DXVECTOR3 v;    v.x = ( ( ( 2.0f * m_Point.x ) / g_pApp->GetScreenSize().x ) - 1 ) / proj._11;    v.y = -( ( ( 2.0f * m_Point.y ) / g_pApp->GetScreenSize().y ) - 1 ) / proj._22;    v.z = 1.0f;    D3DXMATRIX mWorldView = matWorld * matView;    D3DXMATRIX m;    D3DXMatrixInverse( &m, NULL, &mWorldView );    // Transform the screen space Pick ray into 3D space    m_vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;    m_vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;    m_vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;    m_vPickRayOrig.x = m._41;    m_vPickRayOrig.y = m._42;    m_vPickRayOrig.z = m._43;ID3DXMesh* pTempMesh;    V( pMesh->CloneMeshFVF( pMesh->GetOptions(), D3D9Vertex_UnlitTextured::FVF,                                  DXUTGetD3D9Device(), &pTempMesh ) );    LPDIRECT3DVERTEXBUFFER9 pVB;    LPDIRECT3DINDEXBUFFER9 pIB;    pTempMesh->GetVertexBuffer( &pVB );    pTempMesh->GetIndexBuffer( &pIB );WORD* pIndices;D3D9Vertex_UnlitTextured* pVertices;pIB->Lock( 0, 0, ( void** )&pIndices, 0 );pVB->Lock( 0, 0, ( void** )&pVertices, 0 );DWORD intersections = 0;    // When calling D3DXIntersect, one can get just the closest intersection and not    // need to work with a D3DXBUFFER.  Or, to get all intersections between the ray and     // the Mesh, one can use a D3DXBUFFER to receive all intersections.  We show both    // methods.    if( !m_bAllHits )    {        // Collect only the closest intersection        BOOL bHit;        DWORD dwFace;        FLOAT fBary1, fBary2, fDist;        D3DXIntersect( pTempMesh, &m_vPickRayOrig, &m_vPickRayDir, &bHit, &dwFace, &fBary1, &fBary2, &fDist,                       NULL, NULL );        if( bHit )        {            m_NumIntersections = 1;m_IntersectionArray.resize(1);InitIntersection(m_IntersectionArray[0], dwFace, fDist, fBary1, fBary2, actorId, pIndices, pVertices, matWorld);}        else        {            m_NumIntersections = 0;        }    }    else    {        // Collect all intersections        BOOL bHit;        LPD3DXBUFFER pBuffer = NULL;        D3DXINTERSECTINFO* pIntersectInfoArray;        if( FAILED( hr = D3DXIntersect( pTempMesh, &m_vPickRayOrig, &m_vPickRayDir, &bHit, NULL, NULL, NULL, NULL,                                        &pBuffer, &intersections ) ) )        {            SAFE_RELEASE( pTempMesh );            SAFE_RELEASE( pVB );            SAFE_RELEASE( pIB );            return hr;        }        if( intersections > 0 )        {m_IntersectionArray.resize(m_NumIntersections + intersections);            pIntersectInfoArray = ( D3DXINTERSECTINFO* )pBuffer->GetBufferPointer();            if( m_NumIntersections > m_MaxIntersections )                m_NumIntersections = m_MaxIntersections;            for( DWORD i = 0; i < intersections; i++ )            {Intersection* pIntersection;pIntersection = &m_IntersectionArray[i + m_NumIntersections];InitIntersection(*pIntersection, pIntersectInfoArray[i].FaceIndex,pIntersectInfoArray[i].Dist,pIntersectInfoArray[i].U,pIntersectInfoArray[i].V,actorId, pIndices, pVertices, matWorld);            }        }        SAFE_RELEASE( pBuffer );    }m_NumIntersections += intersections;    pVB->Unlock();    pIB->Unlock();    SAFE_RELEASE( pTempMesh );    SAFE_RELEASE( pVB );    SAFE_RELEASE( pIB );return S_OK;}HRESULT RayCast::Pick(Scene *pScene, ActorId actorId, CDXUTSDKMesh *pMesh){if (!m_bAllHits && m_NumIntersections > 0)return S_OK;    IDirect3DDevice9* pD3Device = DXUTGetD3D9Device();// Get the inverse view matrix    const Mat4x4 matView = pScene->GetCamera()->GetView();    const Mat4x4 matWorld = pScene->GetTopMatrix();const Mat4x4 proj = pScene->GetCamera()->GetProjection();    // Compute the vector of the Pick ray in screen space    D3DXVECTOR3 v;    v.x = ( ( ( 2.0f * m_Point.x ) / g_pApp->GetScreenSize().x ) - 1 ) / proj._11;    v.y = -( ( ( 2.0f * m_Point.y ) / g_pApp->GetScreenSize().y ) - 1 ) / proj._22;    v.z = 1.0f;    D3DXMATRIX mWorldView = matWorld * matView;    D3DXMATRIX m;    D3DXMatrixInverse( &m, NULL, &mWorldView );    // Transform the screen space Pick ray into 3D space    m_vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;    m_vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;    m_vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;    m_vPickRayOrig.x = m._41;    m_vPickRayOrig.y = m._42;    m_vPickRayOrig.z = m._43;return E_FAIL;}HRESULT RayCast::Pick(Scene *pScene, ActorId actorId, LPDIRECT3DVERTEXBUFFER9 pVB, LPDIRECT3DINDEXBUFFER9 pIB, DWORD numPolys){if (!m_bAllHits && m_NumIntersections > 0)return S_OK;WORD* pIndices;D3D9Vertex_ColoredTextured* pVertices;pIB->Lock( 0, 0, ( void** )&pIndices, 0 );pVB->Lock( 0, 0, ( void** )&pVertices, 0 );    IDirect3DDevice9* pD3Device = DXUTGetD3D9Device();// Get the inverse view matrix    const Mat4x4 matView = pScene->GetCamera()->GetView();    const Mat4x4 matWorld = pScene->GetTopMatrix();const Mat4x4 proj = pScene->GetCamera()->GetProjection();    // Compute the vector of the Pick ray in screen space    D3DXVECTOR3 v;    v.x = ( ( ( 2.0f * m_Point.x ) / g_pApp->GetScreenSize().x ) - 1 ) / proj._11;    v.y = -( ( ( 2.0f * m_Point.y ) / g_pApp->GetScreenSize().y ) - 1 ) / proj._22;    v.z = 1.0f;    D3DXMATRIX mWorldView = matWorld * matView;    D3DXMATRIX m;    D3DXMatrixInverse( &m, NULL, &mWorldView );    // Transform the screen space Pick ray into 3D space    m_vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;    m_vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;    m_vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;    m_vPickRayOrig.x = m._41;    m_vPickRayOrig.y = m._42;    m_vPickRayOrig.z = m._43;    FLOAT fBary1, fBary2;    FLOAT fDist;    for( DWORD i = 0; i < numPolys; i++ )    {        Vec3 v0 = pVertices[pIndices[3 * i + 0]].position;        Vec3 v1 = pVertices[pIndices[3 * i + 1]].position;        Vec3 v2 = pVertices[pIndices[3 * i + 2]].position;        // Check if the Pick ray passes through this point        if( IntersectTriangle( m_vPickRayOrig, m_vPickRayDir, v0, v1, v2,                               &fDist, &fBary1, &fBary2 ) )        {            if( m_bAllHits || m_NumIntersections == 0 || fDist < m_IntersectionArray[0].m_fDist )            {                if( !m_bAllHits )                    m_NumIntersections = 0;++m_NumIntersections;m_IntersectionArray.resize(m_NumIntersections);Intersection* pIntersection;pIntersection = &m_IntersectionArray[m_NumIntersections-1];InitIntersection(*pIntersection, i, fDist, fBary1, fBary2, actorId, pIndices, pVertices, matWorld);                if( m_NumIntersections == m_MaxIntersections )                    break;            }        }    }pVB->Unlock();    pIB->Unlock();return S_OK;}void RayCast::Sort() { std::sort(m_IntersectionArray.begin(), m_IntersectionArray.end()) ; }
以上就是光线的实现情况,下面是天空场景

2. 天空场景 Sky

#pragma once//========================================================================// Sky.h - implements a sky box in either D3D9 or D3D11//========================================================================#include "Geometry.h"#include "Material.h"#include "Shaders.h"// Forward declarationsclass SceneNode;class Scene;//////////////////////////////////////////////////////// class SkyNode////    Implements a believable sky that follows//  the camera around - this is a base class that the D3D9 and D3D11 classes //    inherit from//////////////////////////////////////////////////////typedef unsigned int  DWORD;typedef unsigned short WORD;typedef unsigned char  BYTE;typedef unsigned int  ActorId;typedef unsigned int  GameViewId;typedef D3DXCOLOR     Color;typedef float         FLOAT;typedef unsigned int  UINT;#ifdef   UNICODEtypedef wchar_t       TCHAR;#elsetypedef unsigned char TCHAR;#endiftypedef unsigned char CHAR;typedef unsigned wchar_t WCHAR;enum HRESULT{    E_INVALIDARG,    E_FAIL,    S_OK,};class SkyNode : public SceneNode{protected:DWORDm_numVerts;DWORDm_sides;const char *m_textureBaseName;shared_ptr<CameraNode>m_camera;boolm_bActive;std::string GetTextureName(const int side);public:SkyNode(const char *textureFile);virtual ~SkyNode() { }HRESULT VPreRender(Scene *pScene);bool VIsVisible(Scene *pScene) const { return m_bActive; }};class D3DSkyNode9 : public SkyNode{protected:LPDIRECT3DTEXTURE9m_pTexture[5];// the sky texturesLPDIRECT3DVERTEXBUFFER9 m_pVerts;// the sky vertspublic:D3DSkyNode9(const char *pTextureBaseName );virtual ~D3DSkyNode9();HRESULT VOnRestore(Scene *pScene);HRESULT VRender(Scene *pScene);};// 增加Shader支持.class D3DSkyNode11 : public SkyNode{public:D3DSkyNode11(const char *pTextureBaseName );virtual ~D3DSkyNode11();HRESULT VOnRestore(Scene *pScene);HRESULT VRender(Scene *pScene);protected:ID3D11Buffer*               m_pIndexBuffer;ID3D11Buffer*               m_pVertexBuffer;GameCode4_Hlsl_VertexShaderm_VertexShader;GameCode4_Hlsl_PixelShaderm_PixelShader;};
//========================================================================// File: Sky.cpp - implements a sky box in D3D9 or D3D11//========================================================================#include "GameCodeStd.h"#include "GameCode.h"#include "D3DRenderer.h"#include "Geometry.h"#include "SceneNodes.h"#include "Shaders.h"#include "Sky.h"////////////////////////////////////////////////////// SkyNode Implementation//////////////////////////////////////////////////////// SkyNode::SkyNode//const ActorId INVALID_ACTOR_ID = 0;enum RenderPass{    RenderPass_0,    RenderPass_Static = RenderPass_0,    RenderPass_Actor,    RenderPass_Sky,    RenderPass_NotRendered,    RenderPass_Last};SkyNode::SkyNode(const char *pTextureBaseName): SceneNode(INVALID_ACTOR_ID, WeakBaseRenderComponentPtr(), RenderPass_Sky, &Mat4x4::g_Identity), m_bActive(true){m_textureBaseName = pTextureBaseName;}//// SkyNode::VPreRender 渲染前准备环境//HRESULT SkyNode::VPreRender(Scene *pScene){Vec3 cameraPos = m_camera->VGet()->ToWorld().GetPosition();Mat4x4 mat = m_Props.ToWorld();mat.SetPosition(cameraPos);VSetTransform(&mat);return SceneNode::VPreRender(pScene);}//// D3DSkyNode9::D3DSkyNode9D3DSkyNode9::D3DSkyNode9(const char *pTextureBaseName): SkyNode(pTextureBaseName){for (int i=0; i<5; ++i){m_pTexture[i] = NULL;}m_pVerts = NULL;}//// D3DSkyNode9::~D3DSkyNode9//#define SAFE_RELEASE(x) if(x) x->Release(); x=NULL;D3DSkyNode9::~D3DSkyNode9(){for (int i=0; i<5; ++i){SAFE_RELEASE(m_pTexture[i]);}SAFE_RELEASE(m_pVerts);}//// D3DSkyNode9::VOnRestore//HRESULT D3DSkyNode9::VOnRestore(Scene *pScene){// Call the base class's restoreSceneNode::VOnRestore(pScene);m_camera = pScene->GetCamera();// added post press!m_numVerts = 20;SAFE_RELEASE(m_pVerts);    if( FAILED( DXUTGetD3D9Device()->CreateVertexBuffer( m_numVerts*sizeof(D3D9Vertex_ColoredTextured),D3DUSAGE_WRITEONLY, D3D9Vertex_ColoredTextured::FVF,        D3DPOOL_MANAGED, &m_pVerts, NULL ) ) )    {        return E_FAIL;    }    // Fill the vertex buffer. We are setting the tu and tv texture    // coordinates, which range from 0.0 to 1.0    D3D9Vertex_ColoredTextured* pVertices;    if( FAILED( m_pVerts->Lock( 0, 0, (void**)&pVertices, 0 ) ) )        return E_FAIL;// Loop through the grid squares and calc the values// of each index. Each grid square has two triangles:////A - B//| / |//C - DD3D9Vertex_ColoredTextured skyVerts[4];D3DCOLOR skyVertColor = 0xffffffff;float dim = 50.0f;skyVerts[0].position = Vec3( dim, dim, dim ); skyVerts[0].color=skyVertColor; skyVerts[0].tu=1; skyVerts[0].tv=0; skyVerts[1].position = Vec3(-dim, dim, dim ); skyVerts[1].color=skyVertColor; skyVerts[1].tu=0; skyVerts[1].tv=0; skyVerts[2].position = Vec3( dim,-dim, dim ); skyVerts[2].color=skyVertColor; skyVerts[2].tu=1; skyVerts[2].tv=1; skyVerts[3].position = Vec3(-dim,-dim, dim ); skyVerts[3].color=skyVertColor; skyVerts[3].tu=0; skyVerts[3].tv=1; Vec3 triangle[3];triangle[0] = Vec3(0.f,0.f,0.f);triangle[1] = Vec3(5.f,0.f,0.f);triangle[2] = Vec3(5.f,5.f,0.f);Vec3 edge1 = triangle[1]-triangle[0];Vec3 edge2 = triangle[2]-triangle[0];Vec3 normal;normal = edge1.Cross(edge2);normal.Normalize();Mat4x4 rotY;rotY.BuildRotationY(GCC_PI/2.0f);Mat4x4 rotX;rotX.BuildRotationX(-GCC_PI/2.0f);m_sides = 5;for (DWORD side = 0; side < m_sides; side++){for (DWORD v = 0; v < 4; v++){Vec4 temp;if (side < m_sides-1){temp = rotY.Xform(Vec3(skyVerts[v].position));}else{skyVerts[0].tu=1; skyVerts[0].tv=1; skyVerts[1].tu=1; skyVerts[1].tv=0; skyVerts[2].tu=0; skyVerts[2].tv=1; skyVerts[3].tu=0; skyVerts[3].tv=0; temp = rotX.Xform(Vec3(skyVerts[v].position));}skyVerts[v].position = Vec3(temp.x, temp.y, temp.z);}memcpy(&pVertices[side*4], skyVerts, sizeof(skyVerts));}m_pVerts->Unlock();return S_OK;}//// D3DSkyNode9::VRender//HRESULT D3DSkyNode9::VRender(Scene *pScene){// Setup our texture. Using textures introduces the texture stage states,    // which govern how textures get blended together (in the case of multiple    // textures) and lighting information. In this case, we are modulating    // (blending) our texture with the diffuse color of the vertices.    DXUTGetD3D9Device()->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );    DXUTGetD3D9Device()->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );    DXUTGetD3D9Device()->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );DXUTGetD3D9Device()->SetStreamSource( 0, m_pVerts, 0, sizeof(D3D9Vertex_ColoredTextured) );DXUTGetD3D9Device()->SetFVF( D3D9Vertex_ColoredTextured::FVF );for (DWORD side = 0; side < m_sides; side++){// FUTURE WORK: A good optimization would be to transform the camera's// world look vector into local space, and do a dot product. If the// result is positive, we shouldn't draw the side since it has to be// behind the camera!// Sky boxes aren't culled by the normal mechanismstd::string name = GetTextureName(side);/***// [mrmike] - This was slightly changed post press, look at the lines below this commented out codeconst char *suffix[] = { "_n.jpg", "_e.jpg",  "_s.jpg",  "_w.jpg",  "_u.jpg" };name += suffix[side];****/Resource resource(name);shared_ptr<ResHandle> texture = g_pApp->m_ResCache->GetHandle(&resource);shared_ptr<D3DTextureResourceExtraData9> extra = static_pointer_cast<D3DTextureResourceExtraData9>(texture->GetExtra());DXUTGetD3D9Device()->SetTexture( 0, extra->GetTexture() );DXUTGetD3D9Device()->DrawPrimitive( D3DPT_TRIANGLESTRIP , 4 * side, 2);}DXUTGetD3D9Device()->SetTexture (0, NULL);return S_OK;}//// D3DSkyNode11::D3DSkyNode11//D3DSkyNode11::D3DSkyNode11(const char *pTextureBaseName) : SkyNode(pTextureBaseName){m_pVertexBuffer = NULL;m_pIndexBuffer = NULL;m_VertexShader.EnableLights(false);}//// D3DSkyNode11::~D3DSkyNode11//D3DSkyNode11::~D3DSkyNode11(){SAFE_RELEASE(m_pVertexBuffer);SAFE_RELEASE(m_pIndexBuffer);}//// D3DSkyNode11::VOnRestore//HRESULT D3DSkyNode11::VOnRestore(Scene *pScene){HRESULT hr;V_RETURN(SceneNode::VOnRestore(pScene) );m_camera = pScene->GetCamera();SAFE_RELEASE(m_pVertexBuffer);SAFE_RELEASE(m_pIndexBuffer);V_RETURN (m_VertexShader.OnRestore(pScene) );V_RETURN (m_PixelShader.OnRestore(pScene) );m_numVerts = 20;    // Fill the vertex buffer. We are setting the tu and tv texture    // coordinates, which range from 0.0 to 1.0    D3D11Vertex_UnlitTextured *pVertices = GCC_NEW D3D11Vertex_UnlitTextured[m_numVerts];GCC_ASSERT(pVertices && "Out of memory in D3DSkyNode11::VOnRestore()");if (!pVertices)return E_FAIL;// Loop through the grid squares and calc the values// of each index. Each grid square has two triangles:////A - B//| / |//C - DD3D11Vertex_UnlitTextured skyVerts[4];D3DCOLOR skyVertColor = 0xffffffff;float dim = 50.0f;skyVerts[0].Pos = Vec3( dim, dim, dim ); skyVerts[0].Uv = Vec2(1.0f, 0.0f); skyVerts[1].Pos = Vec3(-dim, dim, dim ); skyVerts[1].Uv = Vec2(0.0f, 0.0f);skyVerts[2].Pos = Vec3( dim,-dim, dim ); skyVerts[2].Uv = Vec2(1.0f, 1.0f);  skyVerts[3].Pos = Vec3(-dim,-dim, dim ); skyVerts[3].Uv = Vec2(0.0f, 1.0f);Vec3 triangle[3];triangle[0] = Vec3(0.f,0.f,0.f);triangle[1] = Vec3(5.f,0.f,0.f);triangle[2] = Vec3(5.f,5.f,0.f);Vec3 edge1 = triangle[1]-triangle[0];Vec3 edge2 = triangle[2]-triangle[0];Vec3 normal;normal = edge1.Cross(edge2);normal.Normalize();Mat4x4 rotY;rotY.BuildRotationY(GCC_PI/2.0f);Mat4x4 rotX;rotX.BuildRotationX(-GCC_PI/2.0f);m_sides = 5;for (DWORD side = 0; side < m_sides; side++){for (DWORD v = 0; v < 4; v++){Vec4 temp;if (side < m_sides-1){temp = rotY.Xform(Vec3(skyVerts[v].Pos));}else{skyVerts[0].Uv = Vec2(1.0f, 1.0f); skyVerts[1].Uv = Vec2(1.0f, 1.0f);skyVerts[2].Uv = Vec2(1.0f, 1.0f); skyVerts[3].Uv = Vec2(1.0f, 1.0f);temp = rotX.Xform(Vec3(skyVerts[v].Pos));}skyVerts[v].Pos = Vec3(temp.x, temp.y, temp.z);}memcpy(&pVertices[side*4], skyVerts, sizeof(skyVerts));}    D3D11_BUFFER_DESC bd;ZeroMemory( &bd, sizeof(bd) );    bd.Usage = D3D11_USAGE_DEFAULT;    bd.ByteWidth = sizeof( D3D11Vertex_UnlitTextured ) * m_numVerts;    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;bd.CPUAccessFlags = 0;    D3D11_SUBRESOURCE_DATA InitData;ZeroMemory( &InitData, sizeof(InitData) );    InitData.pSysMem = pVertices;    hr = DXUTGetD3D11Device()->CreateBuffer( &bd, &InitData, &m_pVertexBuffer );SAFE_DELETE(pVertices);    if( FAILED( hr ) )        return hr;// Loop through the grid squares and calc the values// of each index. Each grid square has two triangles:////A - B//| / |//C - DWORD *pIndices = GCC_NEW WORD[m_sides * 2 * 3];WORD *current = pIndices;for (DWORD i=0; i<m_sides; i++){// Triangle #1  ACB*(current) = WORD(i*4);*(current+1) = WORD(i*4 + 2);*(current+2) = WORD(i*4 + 1);// Triangle #2  BCD*(current+3) = WORD(i*4 + 1);*(current+4) = WORD(i*4 + 2);*(current+5) = WORD(i*4 + 3);current+=6;}    bd.Usage = D3D11_USAGE_DEFAULT;    bd.ByteWidth = sizeof( WORD ) * m_sides * 2 * 3;        // each side has 2 triangles    bd.BindFlags = D3D11_BIND_INDEX_BUFFER;bd.CPUAccessFlags = 0;    InitData.pSysMem = pIndices;    hr = DXUTGetD3D11Device()->CreateBuffer( &bd, &InitData, &m_pIndexBuffer );SAFE_DELETE_ARRAY(pIndices);    if( FAILED( hr ) )        return hr;return S_OK;}//// D3DSkyNode11::VRender//HRESULT D3DSkyNode11::VRender(Scene *pScene){HRESULT hr;V_RETURN (m_VertexShader.SetupRender(pScene, this) );V_RETURN (m_PixelShader.SetupRender(pScene, this) );    // Set vertex buffer    UINT stride = sizeof( D3D11Vertex_UnlitTextured );    UINT offset = 0;    DXUTGetD3D11DeviceContext()->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );// Set index buffer    DXUTGetD3D11DeviceContext()->IASetIndexBuffer( m_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 );    // Set primitive topology    DXUTGetD3D11DeviceContext()->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );for (DWORD side = 0; side < m_sides; side++){// FUTURTE WORK: A good optimization would be to transform the camera's// world look vector into local space, and do a dot product. If the// result is positive, we shouldn't draw the side since it has to be// behind the camera!// Sky boxes aren't culled by the normal mechanism/***// [mrmike] - This was slightly changed post press, look at the lines below this commented out codeconst char *suffix[] = { "_n.jpg", "_e.jpg",  "_s.jpg",  "_w.jpg",  "_u.jpg" };name += suffix[side];****/std::string name = GetTextureName(side);m_PixelShader.SetTexture(name.c_str());DXUTGetD3D11DeviceContext()->DrawIndexed( 6, side * 6, 0 );}return S_OK;}std::string SkyNode::GetTextureName(const int side){std::string name = m_textureBaseName;char *letters[] = { "n", "e", "s", "w", "u" };unsigned int index = name.find_first_of("_");GCC_ASSERT(index >= 0 && index < name.length()-1);if (index >= 0 && index < name.length()-1){name[index+1] = *letters[side];}return name;}
以上是天空场景的实现,他继承自场景节点~~

下一篇是关于WSAD方向控制 ( MoveController )的实现~~




0 0
原创粉丝点击