游戏架构其九:光线投射和天空 { 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
- 游戏架构其九:光线投射和天空 { Raycast and Sky }
- Physics2D.Raycast 光线投射
- Unity Raycast 光线投射
- Raycast光线投射,Linecast,RaycastAll
- Unity--光线投射碰撞Physics.Raycast和Physics.RaycastAll
- 【unity5学习记录】 raycast光线投射碰撞 17.8.5
- 游戏框架其九:灯光和材质( Lights and Material )
- 光线投射相关算法
- 游戏框架其九:网和着色器( Mesh and Shader )
- 光线投射算法与光线跟踪算法
- 光线投射与光线跟踪算法归纳
- Unity Manual之Physics.Raycast射线投射
- 22. 走进三维:光线投射法
- [VTK] VTK中的光线投射算法
- 使用光线投射实现相机跟随
- [6.837]A1:光线投射法(Ray-Casting)
- 调整物体是否为 Event System Raycast 投射的目标
- (NO.00003)iOS游戏简单的机器人投射游戏成形记(九)
- NYOJ 570欧拉函数求和(欧拉函数&&数论入门)
- BCD编码
- Tomcat源码分析(一)------ 架构
- Java 实现备忘录(Memento)模式
- ios中单例的使用方法以及加线程锁
- 游戏架构其九:光线投射和天空 { Raycast and Sky }
- poj1328
- mac安装pip
- 注意事项
- 单例设计模式
- 几种解决php+mysql中uft-8中文编码乱码的办法
- The type org.springframework.dao.support.DaoSupport cannot be resolved.
- codeforces 476C Dreamoon and Sums
- malloc和new的区别是什么?