zoukankan      html  css  js  c++  java
  • DirectX9:基础篇 第五章 绘制流水线

    一.简介

    绘制流水线也称为渲染管线,在DirectX的固定渲染管线中有九个步骤

    用来创建3D世界几何描述的2D图像,并且设定一个虚拟摄像机把其中需要的部分透视投影到屏幕上

    绘制流水线的流程:局部坐标系->世界坐标系->观察坐标系->背面消隐->光照->投影->裁剪->视口坐标系->光栅化

     

    三维图形的显示和绘制流水线对照可以发现,观察坐标系光照步骤是可以省略的,而背面消隐也可以省略,它属于优化作用,并不是必须的

    二.三大坐标系

    1.局部坐标系

    局部坐标就是模型本身的坐标

    参考DirectX2D/3D--9.0:建立3D场景的几何描述

    2.世界坐标系

    D3DXMATRIX matWorld;
    pd3dDevice->GetTransform(D3DTS_WORLD,&matWorld);

    3.观察坐标系

    观察坐标系就是摄像机的位置

    DirectX是左手坐标系,以屏幕为基准,该坐标系X轴指向右,Y轴指向上,Z轴指向屏幕里面

    //建立虚拟摄影机,相当于渲染视角
     
    D3DXVECTOR3 position(0.0f,0.0f,-5.0f);   //摄像机的位置
    D3DXVECTOR3 target(0.0f,0.0f,0.0f);      //观察点的位置
    D3DXVECTOR3 up(0.0f,1.0f,0.0f);          //向上的坐标系
     
    D3DXMATRIX V;
    D3DXMatrixLookAtLH(&V,&position,&target,&up);  //计算观察矩阵
     
    Device->SetTransform(D3DTS_VIEW,&V);           //绑定观察矩阵
    

    三.摄像机采集数据

    1.背面消隐

    背面消隐就是消除背面朝向相机的多边形,因为一个物体人眼看过去有正面也有背面,把背面剔除可以优化渲染性能

    背面拣选状态也分为三种情况

    参考DX3D9:渲染器状态

    Device->SetRenderState(D3DRS_CULLMODE,DDCULL_NONE);  //禁用背面消隐
    Device->SetRenderState(D3DRS_CULLMODE,DDCULL_CW);  //只对顺时针绕序的三角形消隐
    Device->SetRenderState(D3DRS_CULLMODE,DDCULL_CCW);  //默认值,只对逆时针绕序的三角形消隐
    

    2.光照

    D3D有默认的光照,也可以自定义光照系统,如果没有光照就无法看见物体

    参考DirectX2D/3D--9.0:光照

     

    3.投影

    在3D图形学中有两种基本的投影方式,平行投影(正投影,orthographic projection)和透视投影(perspective projection)

    平行投影中,三维物体的坐标沿平行线投影到观察平面上,保持物体的比例不变

    透视投影中,基于物体相对于投影平面的距离来确定投影的大小,不保持物体的比例.

    DirectX采用透视投影(Perspective Projection),从视锥体投影到平面上

    投影就是从3D空间投影到2D笛卡尔坐标来表示

    D3DXMATRIX* D3DMatrixPerspectiveFovLH(

                                  D3DXMATRIX* pOut,     //获得的投影矩阵

                                   FLOAT fovy,              //y轴向上的视角,角度越大视野也越远

                                  FLOAT Aspect,           //显示的高宽比

                                  FLOAT zn,                  //最近的平面

                                 FLOAT zf                    //最远的平面

    );                 

    //获得投影矩阵
     
    D3DXMATRIX porj;
    D3DXMatrixPerspectiveFovLH(
        &proj,
        D3DX_PI*0.5f,                 //直角
        (float)Width/(float)Height,   //宽高比例
        1.0f,                         //前裁面为1
        1000.0f);                     //后裁面为1000
     
    Device->SetTransform(D3DTS_PROJECTION,&proj);
    

    4.裁剪

    裁剪就是把相机范围之外的物体去除掉,不进行处理,相机只能看到一个锥形范围内的物体.

    可视体由可视角度和前剪裁面(Near Plane)与后剪裁面(Far Plane)决定

    裁剪分为三种情况:

    完全包含:三角形完全在可视体内

    完全在外:三角形完全在可视体外部

    部分在内:三角形一部分在可视体内,一部分在可视体外

    四.摄像机显示

    1.视口坐标系

    视口变换就是将投影过后的2D笛卡尔坐标转化为屏幕上的实际坐标,它把剪裁区域映射到窗口区域

    视口坐标系是以桌面窗口左上角为原点(0,0),横轴X向右为正,纵轴Y轴向下为正

    typedef struct _D3DVIEWPORT9 {

        DWORD X;

        DWORD Y;

        DWORD Width;

        DWORD Height;

        DWORD MinZ;  //最小深度缓冲值

        DWORD MaxZ;  //最大深度缓冲值

    } D3DVIEWPORT9;

    D3DVIEWPORT9 vp={0,0,screenWidth,screenHeight,0,1};
    Device->SetViewport(&vp);
    

    2.光栅化

    光栅化就是将一个多边形光栅化为一个个像素,进行着色处理.

    图元(Graphics Output Primitive)是用来描述几何图元,图元是组成图像的基本单元,比如三维模型中的点/线/面等

    HRESULT IDirect3DDevice9::SetStreamSource(

        UINT StreamNumber,

        IDirect3DVertexBuffer9* pStreamData,

        UINT OffsetInBytes,

        UINT Stride

    );

    HRESULT IDirect3DDevice9::DrawPrimitive(

        D3DPRIMITIVETYPE PrimitiveType,  //图元类型

        UINT StartVertex,  //起始点的索引位置                

        UINT PrimitiveCount  //绘制图元个数

    );

    //绑定资源流
    Device->SetStreamSource(0, vb, 0, sizeof(Vertex));
     
    //设置顶点格式
    Device->SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
     
    //设置索引缓冲区
    Device->SetIndices(ib);
     
     
    //绘制图元方式
    Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,8,0,12);
    Device->Present(0,0,0,0);
    

    五.完整版

    参考代码->DirectX2D/3D--9.0:初始化,代码都不变,添加了一些新代码

    1.三角形绘制

    IDirect3DVertexBuffer9* Triangle=0;
     
    //struct Vertex{
        Vertex(){}
        Vertex(float x,float y,float z){
            _x=x;_y=y;_z=z;
        }
     
        float _x,_y,_z;
        static const DWORD FVF;
    }
    const DWORD Vertex::FVF=D3DFVF_XYZ;
     
    bool Setup(){
     
        //
        //Create the vertex buffer
        //
     
        Device->CreateVertexBuffer(
            3*sizeof(Vertex),      //size in bytes
            D3DUSAGE_WRITEONLY,    //flags
            Vertex::FVF,           //vertex format
            D3DPOOL_MANAGED,       //managed memory pool
            &Triangle,             //return create vertex buffer
            0);
     
        //
        //Fill the buffers with the triangle data
        //      
     
        Vertex* vertices;
        Triangle->Lock(0,0,(void**)&vertices,0);
     
        vertices[0]=Vertex(-1.0f,0.0f,2.0f);
        vertices[1]=Vertex(0.0f,1.0f,2.0f);
        vertices[2]=Vertex(1.0f,0.0f,2.0f);
     
        Triangle->Unlock();
     
        //
        //Set the projection matrix
        //
     
        D3DXMATRIX proj;
        D3DXMatrixPerspectiveFovLH(
            &proj,
            D3DX_PI*0.5f,
            (float)Width/(float)Height,
            1.0f,
            1000.0f);
        Device->SetTransform(D3DTS_PROJECTION,&proj);
     
        //
        //Set wireframe mode render state
        //
        Device->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
     
        return true;
        
    }
     
    void Cleanup(){
        d3d::Release<IDirect3DVertexBuffer9*>(Triangle);
    }
     
    bool Display(float timeDelta){
        if(Device){
            Device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,0xffffffff,1.0f,0);
            Device->BeginScene();
            
            Device->SetStreamSource(0,Triangle,0,sizeof(Vertex));
            Device->SetFVF(Vertex::FVF);
     
            //Draw one triangle
            Device->DrawPrimitive(D3DPI_TRIANGLELIST,0,1);
            
            Device->EndScene();
            Device->Present(0,0,0,0);
        }
        return true;
    }
    

    2.正方形绘制

    IDirect3DVertexBuffer9* VB=0;
    IDirect3DIndexBuffer9* IB=0;
     
    struct Vertex{
       
        Vertex(){}
        Vertex(float x,float y,float z){
            _x=x;_y=y;_z=z;
        }
        float _x,_y,_z;
        static const DWORD FVF;
    };
    const DWORD Vertex::FVF=D3DFVF_XYZ;
     
    bool Setup(){
        
        Device->CreateVertexBuffer(
            8*sizeof(Vertex),
            D3DUSAGE_WRITEONLY,
            Vertex::FVF,
            D3DPOOL_MANAGED,
            &VB,
            0);
     
        Device->CreateIndexBuffer(
            36*sizeof(WORD),
            D3DUSAGE_WRITEONLY,
            D3DFMT_INDEX16,
            D3DPOOL_MANAGED,
            &IB,
            0);
     
        Vertex* vertices;
        VB->Lock(0,0,(void**)&vertices,0);
     
        vertices[0]=Vertex(-1.0f,-1.0f,-1.0f);
        vertices[1]=Vertex(-1.0f,1.0f,-1.0f);
        vertices[2]=Vertex(1.0f,1.0f,-1.0f);
        vertices[3]=Vertex(1.0f,-1.0f,-1.0f);
        vertices[4]=Vertex(-1.0f,-1.0f,1.0f);
        vertices[5]=Vertex(-1.0f,1.0f,1.0f);
        vertices[6]=Vertex(1.0f,1.0f,1.0f);
        vertices[7]=Vertex(1.0f,-1.0f,1.0f);
     
        VB->Unlock();
        
        WORD* indices=0;
        IB->Lock(0,0,(void**)&indices,0);
     
        //front side
        indices[0]=0;indices[1]=1;indices[2]=2;
        indices[3]=0;indices[4]=2;indices[5]=3;
     
        //back side
        indices[6]=4;indices[7]=6;indices[8]=5;
        indices[9]=4;indices[10]=7;indices[11]=6;
     
        //left side
        indices[12]=4;indices[13]=5;indices[14]=1;
        indices[15]=4;indices[16]=1;indices[17]=0;
     
        //right side
        indices[18]=3;indices[19]=2;indices[20]=6;
        indices[21]=3;indices[22]=6;indices[23]=7;
     
        //top
        indices[24]=1;indices[25]=5;indices[26]=6;
        indices[27]=1;indices[28]=6;indices[29]=2;
     
        //bottom
        indices[30]=4;indices[31]=0;indices[32]=3;
        indices[33]=4;indices[34]=3;indices[35]=7;
     
        IB->Unlock();
     
        D3DXVECTOR3 position(0.0f,0.0f,-5.0f);
        D3DXVECTOR3 target(0.0f,0.0f,0.0f);
        D3DXVECTOR3 up(0.0f,1.0f,0.0f);
        D3DXMATRIX V;
        D3DXMatrixLookAtLH(&V,&position,&target,&up);
     
        Device->SetTransform(D3DTS_VIEW,&V);
     
        D3DXMATRIX proj;
        D3DXMatrixPerspectiveFovLH(
            &proj,
            D3DX_PI*0.5f,
            (float)Width/(float)Height,
            1.0f,
            1000.0f);
        Device->SetTransform(D3DTS_PROJECTION,&proj);
     
        Device->SetRenderState(D3DRS_FILEMODE,D3DFILL_WIREFRAME);
        
        return true;
    }
     
    void Cleanup(){
        d3d::Release<IDirect3DVertexBuffer9*>(VB);
        d3d::Release<IDirect3DIndexBuffer9*>(IB);
    }
     
    bool Display(float timeDelta){
     
        if(Device){
            
            D3DXMATRIX Rx,Ry;
            D3DXMatrixRotationX(&Rx,3.14f/4.0f);
     
            static float y=0.0f;
            D3DXMatrixRotationY(&Ry,y);
            y+=timeDelta;
     
            if(y>=6.28f)
                y=0.0f;
     
            D3DXMATRIX p=Rx*Ry;
            Device->SetTransform(D3DTS_WORLD,&p);
     
            Device->Clear(0,0,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,0xffffffff,1.0f,0);
            Device->BeginScene();
            
            Device->SetStreamSource(0,VB,0,sizeof(Vertex));
            Device->SetIndices(IB);
            Device->SetFVF(Vertex::FVF);
            
            Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,0,0,8,0,12);
            Device->EndScene();
            Device->Present(0,0,0,0);
        }
        return true;
    }
    

    六.简化版

     

  • 相关阅读:
    Evolution of Image Classifiers,进化算法在神经网络结构搜索的首次尝试 | ICML 2017
    YOLOv1/v2/v3简述 | 目标检测
    MetaQNN : 与Google同场竞技,MIT提出基于Q-Learning的神经网络搜索 | ICLR 2017
    FCOS : 找到诀窍了,anchor-free的one-stage目标检测算法也可以很准 | ICCV 2019
    canvas图表(3)
    WebGL学习(2)
    canvas图表(1)
    WebGL学习(1)
    前端特效列表
    canvas绘制太阳系
  • 原文地址:https://www.cnblogs.com/k5bg/p/11150822.html
Copyright © 2011-2022 走看看