坐标系与基本图元(6)

坐标系与基本图元(6)

灵活顶点格式

灵活顶点格式(Flexible Vertex Format, FVF)用来描述在顶点缓冲区中的顶点存储格式中包含了哪些属性。Direct3D应用程序可以用几种不同的方式定义灵活顶点格式。灵活顶点格式使应用程序只使用它需要的顶点数据,排除那些它不需要的组成成分。这样,应用程序可以节省内存空间,减少系统带宽。通过D3DFVF的组合,可以描述图元顶点的格式。灵活顶点格式指定的格式包括点的大小,用D3DFVF_PSIZE指定,该大小在投影机空间用来表示未经变换的顶点,在设备空间用来表示经过变换的顶点。

接口IDirect3DDevice9的渲染方法能够接受这些标志的组合,并用它们来决定如何渲染图元。这些标志告诉系统应用程序所使用的顶点的组成,包括顶点的位置、顶点混合权重、法向量、颜色和纹理坐标的格式和数量,以及向Direct3D申请何种渲染流水线。另外,提交或撤销一个具体的顶点格式标志会告诉系统哪些顶点组成单元还留在系统中,哪些已经被忽略了。

纹理坐标可用不同的格式声明,纹理可以由一个坐标寻址,也可以由多达4个纹理坐标来寻址。使用宏集合D3DFVF_TEXCOORDSIZEn可以创建位模式,定义要使用的顶点格式所需的纹理坐标格式。

为了使用索引顶点混合,标志D3DFVF_LASTBETA_UBYTE4应该追加到顶点灵活格式中去。这个标志的出现表明第5个混合权重将被当作一个DWORD值,而不是一个浮点值。

渲染状态

设备渲染状态控制Direct3D设备的光栅化组件的行为。通过改变渲染状态属性,可以控制使用何种着色模式,如何进行雾化及其他光栅化操作。Direct3D编程很大一部分工作就是设置合适的渲染状态。

Direct3D图形程序通过调用IDirect3DDevice9::SetRenderState()函数来设置渲染状态。枚举类型D3DRENDERSTATETYPE列举出所有可能的渲染状态。应用程序将D3DRENDERSTATETYPE类型的某一个枚举值作为第一个参数传递给函数SetRenderState(),然后用第二个参数指定相应的渲染状态。

着色模式

Direct3D中的物体表面是由许许多多的多边形构成的。当渲染一个物体的多边形时,不同的着色模式在其表面产生不同的效果。着色模式决定了多边形上每个点的颜色和光照的强度。Direct3D提供两种着色模式:平面着色模式(FLAT)和戈劳德着色模式(GOURAUD)。

(1)平面着色模式

在平面着色模式下,Direct3D渲染一个多边形时,把多边形第一个顶点的颜色作为整个多边形的颜色进行着色,也就是说,在平面着色模式下,一个多边形内的所有像素的颜色都等于该多边形第一个顶点的颜色。如果这些多边形不共面,用平面着色模式渲染的三维图形将出现明显的陡沿。平面着色模式是渲染速度最快的着色模式。

(2)戈劳德着色模式

当用戈劳德着色渲染一个多边形时,它会先用顶点法向量和灯光参数计算每个顶点的颜色。然后,在该多边形的表面上进行线性插值,进而得到每个像素的颜色。例如,顶点1颜色的红色值为0.8,顶点2颜色的红色至为0.4,使用戈劳德着色模式和RGB颜色模式,Direct3D灯光组件将使这两点连线上中点的颜色的红色值为0.6。

(3)着色模式比较

在平面着色模式中,相邻两个面之间会有明显的边缘,而采用戈劳德着色模式时,边缘处的着色值会由内插运算产生,因而最后会得到一个弯曲的表面。在戈劳德着色模式下,对平面光照的处理要比在平面着色模式下更真实。在平面着色模式下,一个面的颜色是唯一的,但戈劳德着色模式可以使光线更准确地照射在每一个面上。当一个表面距离一个点光源很近时,它们的区别将会更明显地表现出来。

戈劳德着色模式可以使在平面着色模式下多边形间的陡沿变得平滑。然而这样可能会导致马赫带效应(Mach bands)的产生,也就是相邻的颜色或光线带之间不能很平滑的相互融合。对于程序开发人员来说,可以通过增加构成对象的多边形的数目来降低马赫带效应,当然也可以通过提高屏幕分辨率或者增加程序的颜色深度来达到目的。

(4)设置着色模式

Direct3D一次只能选择一种着色模式。默认情况下,选择戈劳德着色模式。在Direct3D图形程序中,调用IDirect3DDevice9:: SetRenderState()方法来改变着色模式。设置状态参数为D3DRS_SHADEMODE,该状态参数值必须是D3DSHADEMODE枚举成员的一个。

Defines constants that describe the supported shading modes.

typedef enum D3DSHADEMODE{    D3DSHADE_FLAT = 1,    D3DSHADE_GOURAUD = 2,    D3DSHADE_PHONG = 3,    D3DSHADE_FORCE_DWORD = 0x7fffffff,} D3DSHADEMODE, *LPD3DSHADEMODE;

Constants

D3DSHADE_FLAT
Flat shading mode. The color and specular component of the first vertex in the triangle are used to determine the color and specular component of the face. These colors remain constant across the triangle; that is, they are not interpolated. The specular alpha is interpolated. See Remarks.
D3DSHADE_GOURAUD
Gouraud shading mode. The color and specular components of the face are determined by a linear interpolation between all three of the triangle‘s vertices.
D3DSHADE_PHONG
Not supported.
D3DSHADE_FORCE_DWORD
Forces this enumeration to compile to 32 bits in size. Without this value, some compilers would allow this enumeration to compile to a size other than 32 bits. This value is not used.

Remarks

The first vertex of a triangle for flat shading mode is defined in the following manner.

  • For a triangle list, the first vertex of the triangle i is i * 3.
  • For a triangle strip, the first vertex of the triangle i is vertex i.
  • For a triangle fan, the first vertex of the triangle i is vertex i + 1.

The members of this enumerated type define the vales for the D3DRS_SHADEMODE render state.

多边形填充模式

默认状态下,Direct3D会把渲染好的多边形面的图像绘制出来,这种方法适合于绝大多数情况。然而,有时为了调试程序或其他特殊目的,可能只需绘制出多边形的顶点或边。这可以通过设置渲染状态D3DRS_FILLMODE来实现,通过为D3DRS_FILLMODE渲染状态指定枚举类型D3DFILLMODE中的一个数值,来选择多边形填充模式。

Defines constants describing the fill mode.

typedef enum D3DFILLMODE{    D3DFILL_POINT = 1,    D3DFILL_WIREFRAME = 2,    D3DFILL_SOLID = 3,    D3DFILL_FORCE_DWORD = 0x7fffffff,} D3DFILLMODE, *LPD3DFILLMODE;

Constants

D3DFILL_POINT
Fill points.
D3DFILL_WIREFRAME
Fill wireframes.
D3DFILL_SOLID
Fill solids.
D3DFILL_FORCE_DWORD
Forces this enumeration to compile to 32 bits in size. Without this value, some compilers would allow this enumeration to compile to a size other than 32 bits. This value is not used.

Remarks

The values in this enumerated type are used by the D3DRS_FILLMODE render state.

着色模式和填充模式示例程序

示例程序RenderState演示了着色模式和填充模式对图形显示结果的影响,在RenderState示例程序中用全局变量g_is_flat和g_fill_mode控制渲染图形使用的着色模式和填充模式,通过单击鼠标左键在两种着色模式之间进行切换,单击鼠标右键在三种填充模式之间进行切换。

Gouraud着色模式

FLAT着色模式

点模式

线模式

完整源代码:

#include <d3d9.h>

#define CLASS_NAME    "GameApp"

#define release_com(p)    do { if(p) { (p)->Release(); (p) = NULL; } } while(0)

IDirect3D9*                g_d3d;
IDirect3DDevice9*        g_device;
IDirect3DVertexBuffer9* g_vertex_buffer;
bool                    g_is_flat    = false;
DWORD                    g_fill_mode = D3DFILL_SOLID;

struct sCustomVertex
{
    float x, y, z, rhw;
    DWORD color;
};

#define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE)

void init_vertices()
{
    sCustomVertex vertices[] =
    {
        { 100.0f, 400.0f, 0.5f, 1.0f, 0xffff0000, },
        { 300.0f,  50.0f, 0.5f, 1.0f, 0xff00ff00, },         
        { 500.0f, 400.0f, 0.5f, 1.0f, 0xff0000ff, },
    };

// push vertex data into vertex buffer

g_device->CreateVertexBuffer(sizeof(vertices), 0, D3DFVF_CUSTOM_VERTEX, D3DPOOL_DEFAULT, &g_vertex_buffer, NULL);

void* ptr;

g_vertex_buffer->Lock(0, sizeof(vertices), (void**)&ptr, 0);
    memcpy(ptr, vertices, sizeof(vertices));
    g_vertex_buffer->Unlock();
}

bool init_d3d(HWND hwnd)
{
    g_d3d = Direct3DCreate9(D3D_SDK_VERSION);

if(g_d3d == NULL)
        return false;

D3DPRESENT_PARAMETERS d3dpp;
    ZeroMemory(&d3dpp, sizeof(d3dpp));

d3dpp.Windowed            = TRUE;
    d3dpp.SwapEffect        = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat    = D3DFMT_UNKNOWN;

if(FAILED(g_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                  &d3dpp, &g_device)))
    {
        return false;
    }

init_vertices();

return true;
}

void cleanup()
{    
    release_com(g_vertex_buffer);
    release_com(g_device);
    release_com(g_d3d);
}

void render()
{
    g_device->SetRenderState(D3DRS_SHADEMODE, g_is_flat ? D3DSHADE_FLAT : D3DSHADE_GOURAUD);
    g_device->SetRenderState(D3DRS_FILLMODE,  g_fill_mode);

g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(5, 5, 5), 1.0f, 0);

g_device->BeginScene();

g_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex));
    g_device->SetFVF(D3DFVF_CUSTOM_VERTEX);    
    g_device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);

g_device->EndScene();

g_device->Present(NULL, NULL, NULL, NULL);
}

LRESULT WINAPI WinProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_LBUTTONDOWN:
        g_is_flat = !g_is_flat;
        break;

case WM_RBUTTONDOWN:
        if(g_fill_mode == D3DFILL_POINT)
            g_fill_mode = D3DFILL_WIREFRAME;
        else if(g_fill_mode == D3DFILL_WIREFRAME)
            g_fill_mode = D3DFILL_SOLID;
        else if(g_fill_mode == D3DFILL_SOLID)
            g_fill_mode = D3DFILL_POINT;

break;

case WM_KEYDOWN:
        switch(wParam)
        {    
        case VK_ESCAPE:
            DestroyWindow(hwnd);
            break;
        }    
        break;

case WM_DESTROY:        
        PostQuitMessage(0);
        return 0;
    }

return DefWindowProc(hwnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR, INT)
{
    WNDCLASSEX wc;

wc.cbSize            = sizeof(WNDCLASSEX);
    wc.style            = CS_CLASSDC;
    wc.lpfnWndProc        = WinProc;
    wc.cbClsExtra        = 0;
    wc.cbWndExtra        = 0;
    wc.hInstance        = inst;
    wc.hIcon            = NULL;
    wc.hCursor            = NULL;
    wc.hbrBackground    = NULL;
    wc.lpszMenuName        = NULL;
    wc.lpszClassName    = CLASS_NAME;
    wc.hIconSm            = NULL;

if(! RegisterClassEx(&wc))
        return -1;

HWND hwnd = CreateWindow(CLASS_NAME, "Direct3D App", WS_OVERLAPPEDWINDOW, 200, 100, 600, 500,
                             NULL, NULL, wc.hInstance, NULL);

if(hwnd == NULL)
        return -1;

if(init_d3d(hwnd))
    {
        ShowWindow(hwnd, SW_SHOWDEFAULT);
        UpdateWindow(hwnd);

MSG msg;
        ZeroMemory(&msg, sizeof(msg));

while(msg.message != WM_QUIT)
        {
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
                
            render();
        }
    }

cleanup();

UnregisterClass(CLASS_NAME, wc.hInstance);

return 0;
}

时间: 2024-10-21 12:50:37

坐标系与基本图元(6)的相关文章

坐标系与基本图元~转载天行健 君子当自强而不息

坐标系与基本图元 坐标系与基本图元(8)      摘要: 游戏程序通常都是运行在全屏幕模式下,进行全屏显示的关键是使用全屏显示的渲染设备.创建全屏显示模式渲染设备同窗口模式渲染设备基本相同,区别是将 d3dpp.Windowed设置为FALSE,告诉Direct3D系统,将要创建的是全屏模式渲染设备.此外,还需要明确指定后台缓冲区的大小和格式,这和创建窗口模式渲染设备是不相同的,在创建窗口模式渲染设备时可将后台缓冲区格式设置为D3DFMT_UNKNOWN,后台缓冲区大小也可取默认值,而在创建全

坐标系与基本图元(3)

坐标系与基本图元(3) 渲染顶点缓冲区图形 void render(){ g_device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_X#050505, 1.0f, 0); g_device->BeginScene(); g_device->SetStreamSource(0, g_vertex_buffer, 0, sizeof(sCustomVertex)); g_device->SetFVF(D3DFVF_CUSTOM_VERTEX)

坐标系与基本图元(7)

坐标系与基本图元(7) 场景提交概述 场景提交即将在后台缓冲区绘制好的场景提交到前台缓冲区,从而在屏幕上显示出来.提交接口函数是一组控制特定的渲染设备状态的方法,这些设备影响显示器的显示. (1)前台缓冲区:这是一块由显卡转换来的矩形存储区,这块矩形存储区的内容显示在显示器或其他输出设备上. (2)后台缓冲区:后台缓冲区是一个表面,其内容可以提交到前台缓冲区. (3)交换链:一组后台缓冲区集合,它们被顺序地提交到前台缓冲区.一般情况下,一个全屏交换链通过翻转设备驱动接口(DDI)来提交随后的显示

坐标系与基本图元(8)

坐标系与基本图元(8) 全屏幕显示 游戏程序通常都是运行在全屏幕模式下,进行全屏显示的关键是使用全屏显示的渲染设备.创建全屏显示模式渲染设备同窗口模式渲染设备基本相同,区别是将d3dpp.Windowed设置为FALSE,告诉Direct3D系统,将要创建的是全屏模式渲染设备.此外,还需要明确指定后台缓冲区的大小和格式,这和创建窗口模式渲染设备是不相同的,在创建窗口模式渲染设备时可将后台缓冲区格式设置为D3DFMT_UNKNOWN,后台缓冲区大小也可取默认值,而在创建全屏模式渲染设备时这些都需要

坐标系与基本图元(1) ~转载天行健 君子当自强而不息

坐标系与基本图元(1) Direct3D基本图元 图元(primitives)是Direct3D中定义的基本图形表示,它是组成一个单一实体的一组顶点.最简单的图元是三维坐标系中多个点的集合,称为点列表(point list).通常,图元是多边形(polygon),一个多边形是由至少三条边组成的封闭图形.最简单的多边形是三角形,Direct3D使用三角形来构成大多数其他多边形,这是因为三角形的三个顶点肯定是共面的,而渲染不共面的顶点效率比较低.通过组合三角形可以形成更大.更复杂的多边形和网格(me

坐标系与基本图元(5)

坐标系与基本图元(5) 使用索引缓冲区绘制图形 当绘制一个比较复杂的图形时,需要使用许多相互邻接的三角形.如果为每个三角形准备三个顶点数据,显然有许多数据是重复的,这样会浪费大量的内存和系统带宽.为了解决这一问题,可以先创建一个顶点缓冲区,将不重复的顶点数据写入顶点缓冲区,然后创建一个顶点索引缓冲区(index buffer),存放各个三角形的顶点索引信息,最后通过顶点索引和顶点数据共同完成图形绘制. 在Direct3D中一个顶点的索引只需要用一个16位或32位的整数表示,因此当多边形的顶点有较

坐标系与基本图元(4)

坐标系与基本图元(4) 各种基本图元的绘制 上面使用顶点缓冲区绘制的是三角形列表图元,前面介绍过Direct3D支持点列表,线段列表.线段条带.三角形列表.三角形条带.三角扇形6种基本图元.下面通过示例程序BasicPrimitive演示各种基本图元的绘制.该示例程序使用同一个顶点缓冲区绘制不同类型的图元,程序中通过一个全局变量标识当前绘制的图元类型,通过单击键盘上的"1" ~ "6"数字键可以在各图元类型之间进行切换,单击空格键可以在线框模式和实体模式之间切换.

坐标系与基本图元(2)

坐标系与基本图元(2) 创建顶点缓冲区 在创建顶点缓冲区之前,需要先定义一个表示顶点的结构类型,描述顶点保存格式的FVF和一个保存顶点的结构数组. struct sCustomVertex{ float x, y, z, rhw; DWORD color;}; #define D3DFVF_CUSTOM_VERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) sCustomVertex vertices[] ={ { 100.0f, 400.0f, 1.0f, 1.0f,

Qt5图形视图框架之概念篇(1)

本章将主要简述Graphics View框架结构的特点.主要包含的元素及坐标系统. 1.Graphics View框架结构的特点: (1)系统可以利用Qt绘图系统的反锯齿.OpenGL工具来改善绘图性能. (2)其支持事件传播结构,可以使图元在场景中的交互能力提高一倍,凸缘可以处理键盘事件和鼠标事件. (3)通过BSP提供快速的图元查找,可以实现实时显示包含数百万图元的大场景. 2.Graphics View的三元素: (1)场景类(QGraphicsScene):本身不可见,是一个放置图元的容