青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

頂點著色器入門(4)

新建網頁 1

17.5.3輪廓勾勒

要完成卡通效果,我們還需要勾勒(outline)輪廓邊(silhouette edge),這比卡通著色稍微復雜一點。

 

17.5.3.1 邊的表示法

我們將一個網格的一條邊表示為一個四元組(構建自2個三角形)——參見圖17.5

我們選擇四元組有兩個原因:我們可以通過調整四元組的尺寸容易地改變邊的厚度,并且我們可以渲染退化的四元組來隱藏某些邊,也即非輪廓邊。在Direct3D中,我們從兩個三角形來構建一個四元組。退化四元組(degenerate quad)是從兩個退化三角形構建而來的四元組。退化三角形(degenerate triangle)是一個面積為零的三角形,或者換句話說,是一個三點位于一線上的三角形。如果我們傳入一個退化三角形到渲染管線,則該三角形顯示為空。這是很有用的,因為如果我們希望隱藏特定三角形,我們可以簡單的退化它而不需要實際的從三角形列表(頂點緩沖)移除它。回想一下,我們只需要顯示輪廓邊——而不是網格的每一條邊。

當我們首先創建一條邊的時候,我們指定其四個頂點,并使其退化,這意味著邊將會被隱藏(渲染時不顯示)。

注意圖17.6中的兩個頂點v0v1,我們設置其頂點法線向量為零向量。然后當我們將邊的頂點送入頂點著色器的時候,頂點著色器將會檢測頂點是否位于輪廓邊上;如果是,則頂點著色器將沿頂點法線的方向偏移頂點位置的標量。觀察法線向量為零的頂點,它不會被偏移。

因此,我們最終以一個非退化四元組(non-degenerate quad)來表示輪廓邊,如圖17.7所示。

 

備注:如果我們沒有設置頂點v0v1的頂點法線為零向量,那么那些頂點就同樣會被偏移。但是如果偏移描述輪廓邊的所有四個頂點,那么我們僅是平移了該退化四元組。通過保持頂點v0v1固定并僅僅偏移頂點v2v3,我們重新生成了四元組。

 

 

17.5.3.2 輪廓邊測試

若兩個三角面face0face1在視圖方向上與兩個不同方向的面共享同一條邊,則該邊為輪廓邊。也就是說,如果一個面是前面(front facing)而另一個面是后面(back facing),那么這條邊就是一條輪廓邊。圖17.8給出了一個輪廓邊和一個非輪廓邊的例子。

 

接下來,為了檢測一個頂點是否在輪廓邊上,我們必須以每個頂點為基礎了解face0 face1的法線向量。我們的邊的頂點數據結構反映如下:

                  
        

struct         VS_INPUT

        

{

        

             vector position    : POSITION;

        

             vector normal      : NORMAL0;

        

             vector faceNormal1 : NORMAL1;

        

             vector faceNormal2 : NORMAL2;

        

};

前兩個分量很直接,但讓我們看看兩個額外的法線向量,它們是faceNormal1faceNormal2。這些向量描述了兩個三角面的面法線,共享邊的頂點位于這兩個面的共享邊上,這兩個面是face0face1

實際檢測頂點是否在共享邊上的數學原理如下。假設我們在視圖空間中,令v為一原點指向檢測頂點的向量——圖17.8,令n0face0的面法線且n1face0的面法線,若下面的不等式為真,則頂點位于輪廓邊上:

1)(v·n0)(v·n1)<0

若兩點積符號相異,則不等式為真,使得不等式左邊為負。回想一下點積的性質:兩個點積的符號相異,這意味著一個三角面是前面而另一個是后面。

現在,考慮一條邊只有一個三角形共享它的情況,如圖17.9,其法線將會被存儲在faceNormal1中。

 

我們定義這種邊總為輪廓邊。要確保頂點著色器將這種邊作為輪廓邊處理,我們要讓faceNormal2 = -faceNormal1。因此,反向的面法線和不等式(1)為真,表示該邊為一輪廓邊。

 

 

17.5.3.3 邊的生成

生成網格的邊是微不足道的;我們簡單的遍歷網格的每個三角面并為三角面上每條邊計算一個四元組(退化的,如圖17.6所示)。注意:每個三角形有三條邊。

對于每條邊上的頂點,我們同樣需要知道共享邊的兩個三角面。一個面是邊所在的三角形。例如,如果要計算第1個面的一條邊,那么第1個面共享該邊。共享該邊的另一個面可以使用網格的鄰接信息找到。

 

 

輪廓邊的實現代碼:

 

OutlineEdges.h:

     /***************************************************************************************
      Generates the outline geometry of a mesh and renders it.  
      Note that we assume mesh vertex formats as described in sMeshVertex.
     ***************************************************************************************/

    
    #ifndef OUTLINE_EDGES_H
    
#define OUTLINE_EDGES_H
    
    #include "d3dUtility.h"
    
    
struct sEdgeVertex
    {
        D3DXVECTOR3 position;
        D3DXVECTOR3 normal;
        D3DXVECTOR3 face_normal_1;
        D3DXVECTOR3 face_normal_2;
    };
    
    
struct sMeshVertex
    {
        D3DXVECTOR3 position;
        D3DXVECTOR3 normal;
    };
    
    
const DWORD MESH_VERTEX_FVF = D3DFVF_XYZ | D3DFVF_NORMAL;
    
    
    ////////////////////////////////////////////////////////////////////////////////////
    

    
class cOutlineEdges
    {
    
private:
        IDirect3DDevice9*                m_device;
        IDirect3DVertexBuffer9*            m_vertex_buffer;
        IDirect3DIndexBuffer9*            m_index_buffer;
        IDirect3DVertexDeclaration9*    m_vertex_decl;
    
        UINT    m_num_verts;
        UINT    m_num_faces;
    
    
public:
        cOutlineEdges(IDirect3DDevice9* device, ID3DXMesh* mesh, ID3DXBuffer* adj_buffer);
        ~cOutlineEdges();
    
        
void render();
    
    
private:
        
bool create_vertex_declaration();
    
        
void get_face_normal(ID3DXMesh* mesh, DWORD face_index, D3DXVECTOR3* face_normal);
    
        
void get_adj_faces_normal(
            ID3DXMesh*        mesh,
            ID3DXBuffer*    adj_buffer,
            DWORD            current_face_index,
            D3DXVECTOR3*    current_face_normal,
            D3DXVECTOR3        adj_face_normals[3]);
    
        
void generate_edge_vertices(ID3DXMesh* mesh, ID3DXBuffer* adj_buffer);
        
void generate_edge_indices(ID3DXMesh* mesh);
    };
    
    
#endif

OutlineEdges.cpp:
     /***************************************************************************************
      Generates the outline geometry of a mesh and renders it.  
      Note that we assume mesh vertex formats as described in sMeshVertex.
     ***************************************************************************************/

    
    #include "OutlineEdges.h"
    
    cOutlineEdges::cOutlineEdges(IDirect3DDevice9* device, ID3DXMesh* mesh, ID3DXBuffer* adj_buffer)
    {
        m_device = device;
    
        m_vertex_buffer = NULL;
        m_index_buffer  = NULL;
        m_vertex_decl    = NULL;
    
        m_num_verts = 0;
        m_num_faces = 0;
    
        generate_edge_vertices(mesh, adj_buffer);
        generate_edge_indices(mesh);
    
        create_vertex_declaration();
    }    
    
    cOutlineEdges::~cOutlineEdges()
    {
        safe_release<IDirect3DVertexBuffer9*>(m_vertex_buffer);
        safe_release<IDirect3DIndexBuffer9*>(m_index_buffer);
        safe_release<IDirect3DVertexDeclaration9*>(m_vertex_decl);
    }
    
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    

    
bool cOutlineEdges::create_vertex_declaration()
    {
        
// typedef struct _D3DVERTEXELEMENT9
        // {
        //     WORD    Stream;     // Stream index
        //     WORD    Offset;     // Offset in the stream in bytes
        //     BYTE    Type;       // Data type
        //     BYTE    Method;     // Processing method
        //     BYTE    Usage;      // Semantics
        //     BYTE    UsageIndex; // Semantic index
        // } D3DVERTEXELEMENT9, *LPD3DVERTEXELEMENT9;
    

        D3DVERTEXELEMENT9 decl[] =
        {
            {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
            {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0},
            {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   1},
            {0, 36, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   2},
    
            D3DDECL_END()
        };
    
        HRESULT hr = m_device->CreateVertexDeclaration(decl, &m_vertex_decl);
    
        
if(FAILED(hr))
        {
            MessageBox(NULL, "CreateVertexDeclaration() - FAILED", "ERROR", MB_OK);
            
return false;
        }
    
        
return true;
    }
    
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    

    
void cOutlineEdges::get_face_normal(ID3DXMesh* mesh, DWORD face_index, D3DXVECTOR3* face_normal)
    {
        sMeshVertex* vertices;
        mesh->LockVertexBuffer(0, (
void**)&vertices);
    
        WORD* indices;
        mesh->LockIndexBuffer(0, (
void**)&indices);
    
        
// get the triangle's indices
    
        WORD vert_index_0 = indices[face_index * 3];
        WORD vert_index_1 = indices[face_index * 3 + 1];
        WORD vert_index_2 = indices[face_index * 3 + 2];
    
        
// now extract the triangles vertices position
    
        D3DXVECTOR3 v0 = vertices[vert_index_0].position;
        D3DXVECTOR3 v1 = vertices[vert_index_1].position;
        D3DXVECTOR3 v2 = vertices[vert_index_2].position;
    
        
// compute face normal
    

        D3DXVECTOR3 edge0 = v1 - v0;
        D3DXVECTOR3 edge1 = v2 - v0;
    
        D3DXVec3Cross(face_normal, &edge0, &edge1);
        D3DXVec3Normalize(face_normal, face_normal);
    
        mesh->UnlockVertexBuffer();
        mesh->UnlockIndexBuffer();
    }
    
    
void cOutlineEdges::get_adj_faces_normal(ID3DXMesh*        mesh, 
                                             ID3DXBuffer*    adj_buffer, 
                                             DWORD            current_face_index, 
                                             D3DXVECTOR3*    current_face_normal, 
                                             D3DXVECTOR3    adj_face_normals[3])
    {
        sMeshVertex* vertices;
        mesh->LockVertexBuffer(0, (
void**)&vertices);
    
        WORD* indices;
        mesh->LockIndexBuffer(0, (
void**)&indices);
    
        get_face_normal(mesh, current_face_index, current_face_normal);
    
        DWORD* adj = (DWORD*) adj_buffer->GetBufferPointer();
    
        
// get adjacent face indices
    
        DWORD adj_face_index_0 = adj[current_face_index * 3];
        DWORD adj_face_index_1 = adj[current_face_index * 3 + 1];
        DWORD adj_face_index_2 = adj[current_face_index * 3 + 2];
    
        
// Get adjacent face normals, if there is no adjacent face, then set the adjacent face normal 
        // to the opposite of the "current_face_normal".  Recall we do this because edges that don't 
        // have an adjacent triangle are automatically considered outline edges. And in order to 
        // make that happen, we need the current face normal and adjacent face normal to point in the 
        // opposite direction.  Also, recall that an entry in the adjacency buffer equal to -1 denotes 
        // that the edge doesn't have an adjacent triangle.
    

        D3DXVECTOR3 adj_face_normal_0, adj_face_normal_1, adj_face_normal_2;
    
        
if(adj_face_index_0 != USHRT_MAX)    // is there an adjacent triangle?
    
    {
            WORD adj_vert_index_0 = indices[adj_face_index_0 * 3];
            WORD adj_vert_index_1 = indices[adj_face_index_0 * 3 + 1];
            WORD adj_vert_index_2 = indices[adj_face_index_0 * 3 + 2];
    
            D3DXVECTOR3 v0 = vertices[adj_vert_index_0].position;
            D3DXVECTOR3 v1 = vertices[adj_vert_index_1].position;
            D3DXVECTOR3 v2 = vertices[adj_vert_index_2].position;
    
            D3DXVECTOR3 edge0 = v1 - v0;
            D3DXVECTOR3 edge1 = v2 - v0;
    
            D3DXVec3Cross(&adj_face_normal_0, &edge0, &edge1);
            D3DXVec3Normalize(&adj_face_normal_0, &adj_face_normal_0);
        }
        
else
        {
            adj_face_normal_0 = -(*current_face_normal);
        }
    
        
if( adj_face_index_1 != USHRT_MAX ) // is there an adjacent triangle?
    
    {
            WORD adj_vert_index_0 = indices[adj_face_index_1 * 3];
            WORD adj_vert_index_1 = indices[adj_face_index_1 * 3 + 1];
            WORD adj_vert_index_2 = indices[adj_face_index_1 * 3 + 2];
    
            D3DXVECTOR3 v0 = vertices[adj_vert_index_0].position;
            D3DXVECTOR3 v1 = vertices[adj_vert_index_1].position;
            D3DXVECTOR3 v2 = vertices[adj_vert_index_2].position;
    
            D3DXVECTOR3 edge0 = v1 - v0;
            D3DXVECTOR3 edge1 = v2 - v0;
    
            D3DXVec3Cross(&adj_face_normal_1, &edge0, &edge1);
            D3DXVec3Normalize(&adj_face_normal_1, &adj_face_normal_1);
        }
        
else
        {
            adj_face_normal_1 = -(*current_face_normal);
        }
        
        
if( adj_face_index_2 != USHRT_MAX ) // is there an adjacent triangle?
    
    {
            WORD adj_vert_index_0 = indices[adj_face_index_2 * 3];
            WORD adj_vert_index_1 = indices[adj_face_index_2 * 3 + 1];
            WORD adj_vert_index_2 = indices[adj_face_index_2 * 3 + 2];
    
            D3DXVECTOR3 v0 = vertices[adj_vert_index_0].position;
            D3DXVECTOR3 v1 = vertices[adj_vert_index_1].position;
            D3DXVECTOR3 v2 = vertices[adj_vert_index_2].position;
    
            D3DXVECTOR3 edge0 = v1 - v0;
            D3DXVECTOR3 edge1 = v2 - v0;
    
            D3DXVec3Cross(&adj_face_normal_2, &edge0, &edge1);
            D3DXVec3Normalize(&adj_face_normal_2, &adj_face_normal_2);
        }
        
else
        {
            adj_face_normal_2 = -(*current_face_normal);
        }
    
        
// save adjacent face normals
    
        adj_face_normals[0] = adj_face_normal_0;
        adj_face_normals[1] = adj_face_normal_1;
        adj_face_normals[2] = adj_face_normal_2;
    
        mesh->UnlockVertexBuffer();
        mesh->UnlockIndexBuffer();
    }
    
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    

    
void cOutlineEdges::generate_edge_vertices(ID3DXMesh* mesh, ID3DXBuffer* adj_buffer)
    {
        
// 3 edges per face and 4 vertices per edge
    
        m_num_verts = mesh->GetNumFaces() * 3 * 4;
    
        m_device->CreateVertexBuffer(
            m_num_verts * 
sizeof(sEdgeVertex),
            D3DUSAGE_WRITEONLY,
            0,    
// using vertex declaration
    
        D3DPOOL_MANAGED,
            &m_vertex_buffer,
            NULL);
    
        sMeshVertex* vertices;
        mesh->LockVertexBuffer(0, (
void**) &vertices);
    
        WORD* indices;
        mesh->LockIndexBuffer(0, (
void**) &indices);
    
        sEdgeVertex* edge_vertices;
        m_vertex_buffer->Lock(0, 0, (
void**) &edge_vertices, 0);
    
        
for(unsigned int i = 0; i < mesh->GetNumFaces(); i++)
        {
            D3DXVECTOR3 current_face_normal;
            D3DXVECTOR3 adj_face_normals[3];
    
            get_adj_faces_normal(mesh, adj_buffer, i, &current_face_normal, adj_face_normals);
    
            
// get the indices for this face
    
            WORD vert_index_0 = indices[i * 3];
            WORD vert_index_1 = indices[i * 3 + 1];
            WORD vert_index_2 = indices[i * 3 + 2];
    
            
// get the vertices for this face
    
            sMeshVertex v0 = vertices[vert_index_0];
            sMeshVertex v1 = vertices[vert_index_1];
            sMeshVertex v2 = vertices[vert_index_2];
    
            
// A        B
            // *--------*
            // |  edge  |
            // *--------*
            // C        D
            //
            // Note, C and D are duplicates of A and B respectively, such that the quad is degenerate.  
            // The vertex shader will un-degenerate the quad if it is a outline edge.
    
            // compute edge0 v0->v1, note adjacent face normal is adj_face_normals[0]
    

            sEdgeVertex A0, B0, C0, D0;
    
            A0.position         = v0.position;
            A0.normal         = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
            A0.face_normal_1 = current_face_normal;
            A0.face_normal_2 = adj_face_normals[0];
    
            B0.position         = v1.position;
            B0.normal         = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
            B0.face_normal_1 = current_face_normal;
            B0.face_normal_2 = adj_face_normals[0];
    
            C0 = A0;
            C0.normal = v0.normal;
    
            D0 = B0;
            D0.normal = v1.normal;
    
            *edge_vertices = A0; edge_vertices++;
            *edge_vertices = B0; edge_vertices++;
            *edge_vertices = C0; edge_vertices++;
            *edge_vertices = D0; edge_vertices++;
    
            
// compute edge0 v1->v2, note adjacent face normal is adj_face_normals[1]
    

            sEdgeVertex A1, B1, C1, D1;
    
            A1.position      = v1.position;
            A1.normal         = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
            A1.face_normal_1 = current_face_normal;
            A1.face_normal_2 = adj_face_normals[1];
    
            B1.position      = v2.position;
            B1.normal        = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
            B1.face_normal_1 = current_face_normal;
            B1.face_normal_2 = adj_face_normals[1];
    
            C1 = A1;
            C1.normal = v1.normal;
            
            D1 = B1;
            D1.normal = v2.normal;
    
            *edge_vertices = A1; ++edge_vertices;
            *edge_vertices = B1; ++edge_vertices;
            *edge_vertices = C1; ++edge_vertices;
            *edge_vertices = D1; ++edge_vertices;    
    
            
// compute edge0 v0->v2, note adjacent face normal is adj_face_normals[2]
    

            sEdgeVertex A2, B2, C2, D2;
    
            A2.position      = v0.position;
            A2.normal        = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
            A2.face_normal_1 = current_face_normal;
            A2.face_normal_2 = adj_face_normals[2];
    
            B2.position      = v2.position;
            B2.normal        = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
            B2.face_normal_1 = current_face_normal;
            B2.face_normal_2 = adj_face_normals[2];
    
            C2 = A2;
            C2.normal = v0.normal;
            
            D2 = B2;
            D2.normal = v2.normal;
    
            *edge_vertices = A2; ++edge_vertices;
            *edge_vertices = B2; ++edge_vertices;
            *edge_vertices = C2; ++edge_vertices;
            *edge_vertices = D2; ++edge_vertices;    
        }
    
        m_vertex_buffer->Unlock();
    
        mesh->UnlockVertexBuffer();
        mesh->UnlockIndexBuffer();
    }
    
    
void cOutlineEdges::generate_edge_indices(ID3DXMesh* mesh)
    {
        DWORD num_edges = mesh->GetNumFaces() * 3;
        m_num_faces        = num_edges * 2;
    
        m_device->CreateIndexBuffer(
            num_edges * 6 * 
sizeof(WORD),    // 2 triangles per edge
    
            D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_index_buffer, NULL);
    
        WORD* indices;
        m_index_buffer->Lock(0, 0, (
void**)&indices, 0);
    
        
// 0        1
        // *--------*
        // |  edge  |
        // *--------*
        // 2        3
    

        
for(WORD i = 0; i < num_edges; i++)
        {
            
// Six indices to define the triangles of the edge, so every edge we skip six entries in the index buffer.  
            // Four vertices to define the edge, so every edge we skip four entries in the vertex buffer.
    
            indices[i * 6]     = i * 4 + 0;
            indices[i * 6 + 1] = i * 4 + 1;
            indices[i * 6 + 2] = i * 4 + 2;
            indices[i * 6 + 3] = i * 4 + 1;
            indices[i * 6 + 4] = i * 4 + 3;
            indices[i * 6 + 5] = i * 4 + 2;
        }
    
        m_index_buffer->Unlock();
    }
    
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    

    
void cOutlineEdges::render()
    {
        m_device->SetVertexDeclaration(m_vertex_decl);
        m_device->SetStreamSource(0, m_vertex_buffer, 0, 
sizeof(sEdgeVertex));
        m_device->SetIndices(m_index_buffer);
    
        m_device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, m_num_verts, 0, m_num_faces);
    }

17.5.4 輪廓邊頂點著色器代碼

我們現在呈現渲染輪廓邊的頂點著色器代碼。這個著色器的主要任務就是確定傳入的頂點是否在輪廓邊上。如果是,頂點著色器就以一定的值,沿頂點法線的方向偏移頂點。

    /*************************************************************************************
      Vertex shader that draws the outline edges of a mesh.
     *************************************************************************************/

    
    matrix g_world_view;
    matrix g_proj;
    
    
static vector BLACK = {0.0f, 0.0f, 0.0f, 0.0f};
    
    
struct sVertexInput
    {
        vector position            : POSITION;
        vector normal            : NORMAL0;
        vector face_normal_1    : NORMAL1;
        vector face_normal_2    : NORMAL2;
    };
    
    
struct sVertexOutput
    {
        vector position : POSITION;
        vector diffuse  : COLOR;
    };
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    

    sVertexOutput main(sVertexInput input)
    {
        sVertexOutput output = (sVertexOutput) 0;
    
        
// transform position to view space
    
        input.position = mul(input.position, g_world_view);
    
        
// Compute a vector in the direction of the vertex from the eye. 
        // Recall the eye is at the origin in view space - eye is just camera position.
    
        vector eye_to_vertex = input.position;
    
        
// Transform normals to view space.  
        // !! Important, set w components to zero since we're transforming vectors.
        // Assume there are no scalings in the world matrix as well.
    

        input.normal.w          = 0.0f;
        input.face_normal_1.w = 0.0f;
        input.face_normal_2.w = 0.0f;
    
        input.normal        = mul(input.normal,           g_world_view);
        input.face_normal_1 = mul(input.face_normal_1, g_world_view);
        input.face_normal_2 = mul(input.face_normal_2, g_world_view);
    
        
// compute the cosine of the angles between the eye_to_vertex vector and the face normals
    
    float dot0 = dot(eye_to_vertex, input.face_normal_1);
        
float dot1 = dot(eye_to_vertex, input.face_normal_2);
    
        
// If cosines are different signs (positive/negative) than we are on a outline edge.  
        // Do the signs differ?
    
    if((dot0 * dot1) < 0.0f)
        {
            
// Yes, then this vertex is on a outline edge, offset the vertex position by some scalar 
            // in the direction of the vertex normal, which scalar value designate outline's tickness.
    
            input.position += 0.1f * input.normal;
        }
    
        
// transform to homogeneous clip space
    
        output.position = mul(input.position, g_proj);
    
        output.diffuse = BLACK;    
// set outline color
    

        
return output;
    }

執行程序:
            /**************************************************************************************************
      Demonstrates cartoon rendering with outline edges using a vertex shader.  
      Note that you will have to switch to the REF device to view this sample if your 
      graphics card does not support vertex shaders.  
      Or you can use software vertex processing: D3DCREATE_SOFTWARE_VERTEXPROCESSING.  
     **************************************************************************************************/

    
    #include "d3dUtility.h"
    #include "OutlineEdges.h"
    
    #pragma warning(disable : 4100)
    
    
#define MESH_TEAPOT        0
    
#define MESH_SPHERE        1
    
#define MESH_TORUS        2
    
#define MESH_CYLINDER    3
    
#define NUM_MESH        4
    
    
const int WIDTH  = 640;
    
const int HEIGHT = 480;
    
    IDirect3DDevice9*        g_device;
    IDirect3DVertexShader9* g_vertex_shader;
    ID3DXConstantTable*        g_constant_table;
    IDirect3DTexture9*        g_shade_texture;
    
    ID3DXMesh*                g_meshes[NUM_MESH];
    D3DXMATRIX                g_world_matrices[NUM_MESH];
    D3DXVECTOR4                g_mesh_colors[NUM_MESH];
    
    D3DXMATRIX                g_proj_matrix;
    
    D3DXHANDLE                g_world_view_handle;
    D3DXHANDLE                g_world_view_proj_handle;
    D3DXHANDLE                g_color_handle;
    D3DXHANDLE                g_dir_to_light_handle;
    
    cOutlineEdges*            g_mesh_outlines[NUM_MESH];
    IDirect3DVertexShader9*    g_outline_shader;
    ID3DXConstantTable*        g_outline_constant_table;
    
    D3DXHANDLE                g_outline_world_view_handle;
    D3DXHANDLE                g_outline_proj_handle;
    
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    

    
bool setup()
    {    
        
// create geometry and compute corresponding world matrix and color for each mesh
    

        ID3DXBuffer* adj_buffer[NUM_MESH];
    
        D3DXCreateTeapot(g_device, &g_meshes[MESH_TEAPOT], &adj_buffer[MESH_TEAPOT]);
        D3DXCreateSphere(g_device, 1.0f, 20, 20, &g_meshes[MESH_SPHERE], &adj_buffer[MESH_SPHERE]);
        D3DXCreateTorus(g_device, 0.5f, 1.0f, 20, 20, &g_meshes[MESH_TORUS], &adj_buffer[MESH_TORUS]);
        D3DXCreateCylinder(g_device, 0.5f, 0.5f, 2.0f, 20, 20, &g_meshes[MESH_CYLINDER], &adj_buffer[MESH_CYLINDER]);
    
        D3DXMatrixTranslation(&g_world_matrices[MESH_TEAPOT],   0.0f,   2.0f, 0.0f);
        D3DXMatrixTranslation(&g_world_matrices[MESH_SPHERE],   0.0f,  -2.0f, 0.0f);
        D3DXMatrixTranslation(&g_world_matrices[MESH_TORUS],    -3.0f,  0.0f, 0.0f);
        D3DXMatrixTranslation(&g_world_matrices[MESH_CYLINDER],  3.0f,  0.0f, 0.0f);
    
        g_mesh_colors[MESH_TEAPOT]   = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);
        g_mesh_colors[MESH_SPHERE]   = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);
        g_mesh_colors[MESH_TORUS]    = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f);
        g_mesh_colors[MESH_CYLINDER] = D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f);
    
        
// allocate mesh outlines
    
        g_mesh_outlines[MESH_TEAPOT]   = new cOutlineEdges(g_device, g_meshes[MESH_TEAPOT],   adj_buffer[MESH_TEAPOT]);
        g_mesh_outlines[MESH_SPHERE]   = 
new cOutlineEdges(g_device, g_meshes[MESH_SPHERE],   adj_buffer[MESH_SPHERE]);
        g_mesh_outlines[MESH_TORUS]       = 
new cOutlineEdges(g_device, g_meshes[MESH_TORUS],    adj_buffer[MESH_TORUS]);
        g_mesh_outlines[MESH_CYLINDER] = 
new cOutlineEdges(g_device, g_meshes[MESH_CYLINDER], adj_buffer[MESH_CYLINDER]);
    
        safe_release<ID3DXBuffer*>(adj_buffer[MESH_TEAPOT]);
        safe_release<ID3DXBuffer*>(adj_buffer[MESH_SPHERE]);
        safe_release<ID3DXBuffer*>(adj_buffer[MESH_TORUS]);
        safe_release<ID3DXBuffer*>(adj_buffer[MESH_CYLINDER]);
    
        
// compile cartoon shader
    

        ID3DXBuffer*    shader_buffer;
        ID3DXBuffer*    error_buffer;
    
        HRESULT hr = D3DXCompileShaderFromFile("ToonShader.cxx", NULL, NULL, "main", "vs_1_1",
                                               D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY,
                                               &shader_buffer, &error_buffer, &g_constant_table);
    
        
// output any error messages
    
    if(error_buffer)
        {
            MessageBox(NULL, (
char*)error_buffer->GetBufferPointer(), "ERROR", MB_OK);
            safe_release<ID3DXBuffer*>(error_buffer);
        }
    
        
if(FAILED(hr))
        {
            MessageBox(NULL, "D3DXCreateEffectFromFile() - FAILED", "ERROR", MB_OK);
            
return false;
        }
    
        hr = g_device->CreateVertexShader((DWORD*) shader_buffer->GetBufferPointer(), &g_vertex_shader);
    
        
if(FAILED(hr))
        {
            MessageBox(NULL, "CreateVertexShader - FAILED", "ERROR", MB_OK);
            
return false;
        }
    
        safe_release<ID3DXBuffer*>(shader_buffer);
    
        
// compile outline shader
    

        ID3DXBuffer* outline_shader_buffer;
        ID3DXBuffer* outline_error_buffer;
    
        hr = D3DXCompileShaderFromFile("OutlineShader.cxx", NULL, NULL, "main", "vs_1_1",
                    D3DXSHADER_DEBUG, &outline_shader_buffer, &outline_error_buffer, &g_outline_constant_table);
    
        
// output any error messages
    
    if(outline_error_buffer)
        {
            MessageBox(NULL, (
char*) outline_error_buffer->GetBufferPointer(), "ERROR", MB_OK);
            safe_release<ID3DXBuffer*>(outline_error_buffer);
        }
    
        
if(FAILED(hr))
        {
            MessageBox(NULL, "D3DXCompileShaderFromFile() - FAILED", "ERROR", MB_OK);
            
return false;
        }
    
        hr = g_device->CreateVertexShader((DWORD*) outline_shader_buffer->GetBufferPointer(), &g_outline_shader);
    
        
if(FAILED(hr))
        {
            MessageBox(NULL, "CreateVertexShader - FAILED", "ERROR", MB_OK);
            
return false;
        }
    
        safe_release<ID3DXBuffer*>(outline_shader_buffer);
    
        
// load textures
    
        D3DXCreateTextureFromFile(g_device, "toonshade.bmp", &g_shade_texture);
    
        g_device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
        g_device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
        g_device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);        
// disable mipmap
    
        // get handles
    
        g_world_view_handle            = g_constant_table->GetConstantByName(NULL, "g_world_view");
        g_world_view_proj_handle    = g_constant_table->GetConstantByName(NULL, "g_world_view_proj");
        g_color_handle                = g_constant_table->GetConstantByName(NULL, "g_color");        
        g_dir_to_light_handle        = g_constant_table->GetConstantByName(NULL, "g_dir_to_light");
    
        g_outline_world_view_handle = g_outline_constant_table->GetConstantByName(NULL, "g_world_view");
        g_outline_proj_handle        = g_outline_constant_table->GetConstantByName(NULL, "g_proj");
    
        
// set shader constants
    

        D3DXVECTOR4 dir_to_light(-0.57f, 0.57f, -0.57f, 0.0f);
        g_constant_table->SetVector(g_device, g_dir_to_light_handle, &dir_to_light);
    
        g_constant_table->SetDefaults(g_device);
        g_outline_constant_table->SetDefaults(g_device);
    
        
// set the projection matrix
    
        D3DXMatrixPerspectiveFovLH(&g_proj_matrix, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
        
        
//g_device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);
    
    
        
return true;
    }
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    

    
void cleanup()
    {    
        
for(int i = 0; i < NUM_MESH; i++)
        {
            safe_release<ID3DXMesh*>(g_meshes[i]);
            safe_delete<cOutlineEdges*>(g_mesh_outlines[i]);
        }
    
        safe_release<IDirect3DTexture9*>(g_shade_texture);
        safe_release<IDirect3DVertexShader9*>(g_vertex_shader);
        safe_release<ID3DXConstantTable*>(g_constant_table);    
        safe_release<IDirect3DVertexShader9*>(g_outline_shader);
        safe_release<ID3DXConstantTable*>(g_outline_constant_table);
    }
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    

    
bool display(float time_delta)
    {    
        
static float angle  = (3.0f * D3DX_PI) / 2.0f;
        
static float height = 5.0f;
    
        
if(GetAsyncKeyState(VK_LEFT) & 0x8000f)
            angle -= 0.5f * time_delta;
    
        
if(GetAsyncKeyState(VK_RIGHT) & 0x8000f)
            angle += 0.5f * time_delta;
    
        
if(GetAsyncKeyState(VK_UP) & 0x8000f)
            height += 5.0f * time_delta;
    
        
if(GetAsyncKeyState(VK_DOWN) & 0x8000f)
            height -= 5.0f * time_delta;
    
        D3DXVECTOR3 position(cosf(angle) * 7.0f, height, sinf(angle) * 7.0f);
        D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
        D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    
        D3DXMATRIX view_matrix;
        D3DXMatrixLookAtLH(&view_matrix, &position, &target, &up);    
        
        
// render now
    

        g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xFFFFFFFF, 1.0f, 0);
    
        g_device->BeginScene();
    
        
// draw cartoon
    

        g_device->SetVertexShader(g_vertex_shader);
        g_device->SetTexture(0, g_shade_texture);
    
        D3DXMATRIX world_view, world_view_proj;
    
        
for(int i = 0; i < NUM_MESH; i++)
        {
            world_view        = g_world_matrices[i] * view_matrix;
            world_view_proj = g_world_matrices[i] * view_matrix * g_proj_matrix;
    
            g_constant_table->SetMatrix(g_device, g_world_view_handle,        &world_view);
            g_constant_table->SetMatrix(g_device, g_world_view_proj_handle, &world_view_proj);
    
            g_constant_table->SetVector(g_device, g_color_handle,            &g_mesh_colors[i]);
    
            g_meshes[i]->DrawSubset(0);
        }    
    
        
// draw outlines
    

        g_device->SetVertexShader(g_outline_shader);
        g_device->SetTexture(0, NULL);
    
        
// !! Important, do not cull back faces.
    
        g_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
    
        
for(int i = 0; i < NUM_MESH; i++)
        {
            world_view = g_world_matrices[i] * view_matrix;
    
            g_outline_constant_table->SetMatrix(g_device, g_outline_world_view_handle, &world_view);
            g_outline_constant_table->SetMatrix(g_device, g_outline_proj_handle,       &g_proj_matrix);
    
            g_mesh_outlines[i]->render();
        }
    
        
// restore to cull back faces with counterclockwise vertices
    
        g_device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
        
        g_device->EndScene();
    
        g_device->Present(NULL, NULL, NULL, NULL);
    
        
return true;
    }
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    

    LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
    {
        
switch(msg)
        {
        
case WM_DESTROY:
            PostQuitMessage(0);
            
break;
    
        
case WM_KEYDOWN:
            
if(word_param == VK_ESCAPE)
                DestroyWindow(hwnd);
    
            
break;
        }
    
        
return DefWindowProc(hwnd, msg, word_param, long_param);
    }
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
    

    
int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
    {
        
if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_device))
        {
            MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
            
return 0;
        }
    
        
if(! setup())
        {
            MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
            
return 0;
        }
    
        enter_msg_loop(display);
    
        cleanup();
        g_device->Release();
    
        
return 0;
    }

運行截圖:

下載源程序


posted on 2008-04-09 14:42 lovedday 閱讀(2445) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美性猛交视频| 午夜精品电影| 久久精品国产视频| 国产欧美日韩在线| 另类激情亚洲| 一区二区三区鲁丝不卡| 久久九九国产精品| 久久一区国产| 在线亚洲欧美视频| 欧美凹凸一区二区三区视频| 亚洲午夜精品一区二区| 国产亚洲欧洲一区高清在线观看| 看欧美日韩国产| 开心色5月久久精品| 欧美黄色免费网站| 久久久久中文| 正在播放亚洲一区| 午夜精品福利电影| 中日韩高清电影网| 午夜视频精品| 亚洲自拍三区| 亚洲最新视频在线播放| 欧美激情一区在线观看| 久久久久九九九九| 欧美11—12娇小xxxx| 亚洲日韩欧美一区二区在线| 欧美伦理在线观看| 新狼窝色av性久久久久久| 可以看av的网站久久看| 欧美精品福利| 欧美日韩一区二区三区视频| 欧美成人午夜剧场免费观看| 欧美在线视频一区| 亚洲欧美日韩成人| 六月天综合网| 免费在线视频一区| 你懂的国产精品| 国产精品美女诱惑| 国产精品视频免费观看| 国产精品一区二区在线观看| 欧美日一区二区三区在线观看国产免| 欧美成人一区二区三区在线观看| 欧美色视频在线| 91久久精品日日躁夜夜躁欧美| 在线播放日韩欧美| 亚洲高清免费| 一本色道久久加勒比精品| 一区二区三区精品| 亚洲欧美久久久久一区二区三区| 亚洲午夜在线观看视频在线| 免费观看成人| 日韩一区二区久久| 亚洲尤物视频网| 欧美中文字幕视频| 国产精品草莓在线免费观看| 日韩视频精品| 久久久国产成人精品| 一区二区免费在线观看| 欧美激情第8页| 亚洲精品久久久久久下一站| 中文日韩在线视频| 久久久久久日产精品| 另类春色校园亚洲| 亚洲国产一二三| 亚洲一区二区三区高清不卡| 欧美日韩亚洲一区三区 | 欧美三级免费| 亚洲视频欧美视频| 亚洲天堂av在线免费| 久久永久免费| 亚洲第一精品影视| 欧美一区二区黄色| 亚洲第一区中文99精品| 亚洲欧美国产不卡| 国产欧美在线观看| 久久久免费观看视频| 老司机成人网| 一本色道久久综合亚洲精品婷婷| 日韩一级不卡| 国产精品亚洲а∨天堂免在线| 欧美在线不卡视频| 久久久噜噜噜| 99视频热这里只有精品免费| 亚洲激情一区二区三区| 国产欧美日韩在线观看| 欧美一区二区在线视频| 久久精品国产视频| 国产精品xxxxx| 欧美影院精品一区| 久久久夜夜夜| 99精品视频一区二区三区| 久久精品视频网| 久久精品二区| 中文欧美在线视频| 久久久蜜臀国产一区二区| 日韩一区二区免费高清| 亚洲欧美日韩在线| 亚洲精品欧美一区二区三区| 亚洲永久免费观看| 亚洲国产精品尤物yw在线观看 | 亚洲香蕉视频| 永久久久久久| 99热这里只有成人精品国产| 韩国女主播一区| 久久精品视频免费播放| 欧美高清视频| 久久一区二区精品| 久久婷婷国产综合国色天香| 在线亚洲成人| 美女诱惑一区| 久久午夜精品| 国产精品自拍视频| 日韩亚洲在线| 99re8这里有精品热视频免费 | 欧美日韩中文字幕日韩欧美| 欧美sm视频| 国产亚洲人成a一在线v站| 亚洲剧情一区二区| 国产精品国色综合久久| 欧美一区二区精品在线| 欧美精品色网| 欧美激情中文不卡| 亚洲国产日韩一区| 久久精品首页| 亚洲精品老司机| 久久精品一区| 久久久91精品国产一区二区精品| 国产精品av久久久久久麻豆网| 亚洲精品1区2区| 亚洲精品国产日韩| 欧美成人精品h版在线观看| 久久精品国产在热久久 | 销魂美女一区二区三区视频在线| 亚洲精品久久久蜜桃| 另类欧美日韩国产在线| 久久一区激情| 激情欧美一区二区三区| 亚洲日本电影在线| 亚洲美女毛片| 欧美日韩高清在线| 久久爱另类一区二区小说| 久久久999| 欧美色精品在线视频| 欧美高清在线| 欧美一区二区三区另类| 在线播放亚洲一区| 久久久久欧美精品| 免费观看一区| 亚洲美女福利视频网站| 欧美女同在线视频| 中文成人激情娱乐网| 欧美亚洲综合另类| 国内外成人在线| 亚洲美女中文字幕| 亚洲一区二区久久| 国产精品日韩欧美大师| 亚洲欧美在线x视频| 久久一二三四| 日韩小视频在线观看专区| 欧美视频二区| 欧美在线一区二区三区| 欧美电影免费观看高清| 日韩亚洲精品在线| 国产精品夜夜嗨| 久久久蜜桃一区二区人| 亚洲免费av电影| 久久一日本道色综合久久| 亚洲日本视频| 国产精品自在在线| 欧美成人免费网| 亚洲欧美日韩在线观看a三区| 老司机一区二区三区| 一本色道久久88综合亚洲精品ⅰ| 国产欧美日韩在线| 欧美精品免费在线| 欧美在线黄色| 亚洲精品一区二区三区福利| 久久精品国产免费观看| 一区二区三区欧美日韩| 好男人免费精品视频| 国产精品超碰97尤物18| 免费在线欧美视频| 久久精品国产96久久久香蕉| 亚洲开发第一视频在线播放| 久久视频在线看| 亚洲自拍三区| 国产精一区二区三区| 美女主播一区| 欧美一区二区| 国产精品99久久久久久久女警 | 久久精品亚洲热| 一本色道综合亚洲| 欧美激情综合| 麻豆成人在线播放| 欧美一区综合| 亚洲愉拍自拍另类高清精品| 亚洲欧洲综合另类| 在线高清一区| 红桃视频国产精品| 国产一区二区三区精品欧美日韩一区二区三区 |