Lesson 14: SDK文档:Tutorial02 Rendering a Triangle分析

头文件:

#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <xnamath.h>
#include "resource.h"

结构体声明:

// Structures
struct SimpleVertex
{
    D3DXVECTOR3 Pos;
};

全局变量声明:

// Global Variables
HINSTANCE               g_hInst = NULL; //实例句柄
HWND                    g_hWnd = NULL;  //窗口句柄
D3D_DRIVER_TYPE         g_driverType = D3D_DRIVER_TYPE_NULL;    //驱动类型
D3D_FEATURE_LEVEL       g_featureLevel = D3D_FEATURE_LEVEL_11_0;    //特征等级
ID3D11Device*           g_pd3dDevice = NULL;    //设备接口指针
ID3D11DeviceContext*    g_pImmediateContext = NULL; //设备上下文接口指针
IDXGISwapChain*         g_pSwapChain = NULL;    //交换链接口指针
ID3D11RenderTargetView* g_pRenderTargetView = NULL; //渲染目标视图接口指针
ID3D11VertexShader*     g_pVertexShader = NULL; //顶点着色器接口指针
ID3D11PixelShader*      g_pPixelShader = NULL;  //像素着色器接口指针
ID3D11InputLayout*      g_pVertexLayout = NULL; //输入布局接口指针
ID3D11Buffer*           g_pVertexBuffer = NULL; //缓冲区接口指针

注:
D3D10_DRIVER_TYPE的MSDN资料:
https://msdn.microsoft.com/pt-br/library/windows/apps/bb205042.aspx

函数声明:

// Forward declarations
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );    //初始化窗口函数
HRESULT InitDevice();   //初始化设备函数
void CleanupDevice();   //清除设备函数
LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );  //窗口过程函数
void Render();  //渲染函数

程序的入口点函数:

// Entry point to the program. Initializes everything and goes into a message processing loop. Idle time is used to render the scene.
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
    UNREFERENCED_PARAMETER( hPrevInstance );
    UNREFERENCED_PARAMETER( lpCmdLine );

    //初始化窗口
    if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
        return 0;

    //初始化设备
    if( FAILED( InitDevice() ) )
    {
        //初始化失败,清除设备
        CleanupDevice();
        return 0;
    }

    //消息主循环
    // Main message loop
    //消息结构体MSG
    MSG msg = {0};
    //当没有接收到退出程序消息时,继续循环
    while( WM_QUIT != msg.message )
    {
        //获取消息
        //如果有消息,则对消息进行转译、分发
        if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
        {
            TranslateMessage( &msg );
            DispatchMessage( &msg );
        }
        //如果没有消息,则进行渲染
        else
        {
            Render();
        }
    }

    //清除设备
    CleanupDevice();

    return ( int )msg.wParam;
}

初始化窗口函数:

// 该函数用于注册窗口类以及创建窗口
// Register class and create window
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
    // 注册窗口类
    // Register class
    WNDCLASSEX wcex;
    wcex.cbSize = sizeof( WNDCLASSEX );
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
    wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
    wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = L"TutorialWindowClass";
    wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
    //如果注册失败,返回
    if( !RegisterClassEx( &wcex ) )
        return E_FAIL;

    // 创建窗口
    // Create window
    g_hInst = hInstance;

    // 创建客户区矩形
    RECT rc = { 0, 0, 640, 480 };
    // 依据所需客户矩形的大小,计算需要的窗口矩形的大小
    AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
    // 创建所需客户区大小的窗口
    g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 10 Tutorial 2: Rendering a Triangle",
                           WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
                           NULL );
    // 创建失败,返回
    if( !g_hWnd )
        return E_FAIL;

    //显示窗口
    ShowWindow( g_hWnd, nCmdShow );

    return S_OK;
}

辅助编译着色器函数:

// Helper for compiling shaders with D3DX11
HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
    HRESULT hr = S_OK;

    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
    // Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
    // Setting this flag improves the shader debugging experience, but still allows 
    // the shaders to be optimized and to run exactly the way they will run in 
    // the release configuration of this program.
    dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif

    //声明一个内存块接口指针
    ID3DBlob* pErrorBlob;
    //调用D3DX11CompileFromFile函数编译着色器
    hr = D3DX11CompileFromFile( szFileName, NULL, NULL, szEntryPoint, szShaderModel, 
        dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
    if( FAILED(hr) )
    {
        if( pErrorBlob != NULL )
            OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
        if( pErrorBlob ) pErrorBlob->Release();
        return hr;
    }
    if( pErrorBlob ) pErrorBlob->Release();

    return S_OK;
}

初始化设备函数:

// 创建Direct3D设备和交换链
// Create Direct3D device and swap chain
HRESULT InitDevice()
{
    HRESULT hr = S_OK;

    // 矩形rc,用于获得客户区矩形
    RECT rc;
    GetClientRect( g_hWnd, &rc );
    // 计算窗口的宽度和高度
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

    UINT createDeviceFlags = 0;
#ifdef _DEBUG
    // 把createDeviceFlags除去D3D10_CREATE_DEVICE_DEBUG这种属性
    createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
#endif

    // 设置驱动类型
    D3D10_DRIVER_TYPE driverTypes[] =
    {
        D3D10_DRIVER_TYPE_HARDWARE,
        D3D10_DRIVER_TYPE_REFERENCE,
    };
    // 计算驱动类型数量
    UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] );

    // 设置特征等级
    D3D_FEATURE_LEVEL featureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
    };
    // 计算特征等级数量
    UINT numFeatureLevels = ARRAYSIZE( featureLevels );

    // 交换链结构体
    DXGI_SWAP_CHAIN_DESC sd;
    // 清空内存
    ZeroMemory( &sd, sizeof( sd ) );
    // 填充交换链结构体
    sd.BufferCount = 1;
    sd.BufferDesc.Width = width;
    sd.BufferDesc.Height = height;
    sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator = 60;
    sd.BufferDesc.RefreshRate.Denominator = 1;
    sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    sd.OutputWindow = g_hWnd;
    sd.SampleDesc.Count = 1;
    sd.SampleDesc.Quality = 0;
    sd.Windowed = TRUE;

    // 为每种驱动类型创建设备和交换链
    for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
    {
        g_driverType = driverTypes[driverTypeIndex];
        hr = D3D10CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags,
                                            D3D10_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice );
        if( SUCCEEDED( hr ) )
            break;
    }
    // 创建失败,返回
    if( FAILED( hr ) )
        return hr;

    // Create a render target view
    // 声明2D纹理接口
    ID3D10Texture2D* pBuffer;
    // 获得2D纹理的缓冲区地址
    hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), ( LPVOID* )&pBuffer );
    if( FAILED( hr ) )
        return hr;

    // 创建渲染目标视图
    hr = g_pd3dDevice->CreateRenderTargetView( pBuffer, NULL, &g_pRenderTargetView );
    pBuffer->Release();
    if( FAILED( hr ) )
        return hr;

    // 设置渲染目标
    g_pd3dDevice->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );

    // 设置视口
    // Setup the viewport
    // 声明视口结构体
    D3D10_VIEWPORT vp;
    // 填充视口结构体
    vp.Width = width;
    vp.Height = height;
    vp.MinDepth = 0.0f;
    vp.MaxDepth = 1.0f;
    vp.TopLeftX = 0;
    vp.TopLeftY = 0;
    // 设置视口
    g_pd3dDevice->RSSetViewports( 1, &vp );

    // Compile the vertex shader
    // 编译顶点着色器
    // 声明顶点着色器的内存块接口
    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile( L"Tutorial02 d3d11.fx", "VS", "vs_4_0", &pVSBlob );
    if( FAILED( hr ) )
    {
        //编译失败,弹出消息盒子
        MessageBox( NULL,
                    L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
        return hr;
    }

    // 创建顶点着色器
    // Create the vertex shader
    hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader );
    if( FAILED( hr ) )
    {   
        pVSBlob->Release();
        return hr;
    }

    // 定义输入布局
    // Define the input layout
    D3D10_INPUT_ELEMENT_DESC layout[] =
    {
        // 只有POSITION这一个描述内容
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
    };
    // 计算输入布局的元素数量
    UINT numElements = sizeof( layout ) / sizeof( layout[0] );

    // 创建输入布局
    // Create the input layout
    D3D10_PASS_DESC PassDesc;
    g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );
    hr = g_pd3dDevice->CreateInputLayout( layout, numElements, PassDesc.pIAInputSignature,
                                          PassDesc.IAInputSignatureSize, &g_pVertexLayout );
    if( FAILED( hr ) )
        return hr;

    // 设置输入布局
    // Set the input layout
    g_pd3dDevice->IASetInputLayout( g_pVertexLayout );

    // 编译像素着色器
    // Compile the pixel shader
    // 声明像素着色器的内存块
    ID3DBlob* pPSBlob = NULL;
    // 调用CompileShaderFromFile函数完成编译
    hr = CompileShaderFromFile( L"Tutorial02 d3d11.fx", "PS", "ps_4_0", &pPSBlob );
    if( FAILED( hr ) )
    {
        //编译失败,弹出消息盒子
        MessageBox( NULL,
                    L"The FX file cannot be compiled.  Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
        return hr;
    }

    // 创建像素着色器
    // Create the pixel shader
    hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader );
    pPSBlob->Release();
    if( FAILED( hr ) )
        return hr;

    // 创建顶点缓存
    // Create vertex buffer
    SimpleVertex vertices[] =
    {
        D3DXVECTOR3( 0.0f, 0.5f, 0.5f ),
        D3DXVECTOR3( 0.5f, -0.5f, 0.5f ),
        D3DXVECTOR3( -0.5f, -0.5f, 0.5f ),
    };
    // 声明顶点缓存结构体
    D3D10_BUFFER_DESC bd;
    ZeroMemory( &bd, sizeof(bd) );
    // 填充顶点缓存结构体
    bd.Usage = D3D10_USAGE_DEFAULT;
    bd.ByteWidth = sizeof( SimpleVertex ) * 3;
    bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = 0;
    // 声明SUBRESOURCE数据
    D3D10_SUBRESOURCE_DATA InitData;
    ZeroMemory( &InitData, sizeof(InitData) );
    // 拷贝顶点数据
    InitData.pSysMem = vertices;
    //调用CreateBuffer函数创建顶点缓存
    hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
    if( FAILED( hr ) )
        return hr;

    // 设置顶点缓存
    // Set vertex buffer
    // 步值为顶点的大小
    UINT stride = sizeof( SimpleVertex );
    // 偏移值为0
    UINT offset = 0;
    g_pd3dDevice->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );

    // 设置原始拓扑
    // Set primitive topology
    // 设为三角形列表
    g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

    return S_OK;
}

清除设备函数:

// Clean up the objects we've created
void CleanupDevice()
{
    if( g_pImmediateContext ) g_pImmediateContext->ClearState();

    if( g_pVertexBuffer ) g_pVertexBuffer->Release();
    if( g_pVertexLayout ) g_pVertexLayout->Release();
    if( g_pVertexShader ) g_pVertexShader->Release();
    if( g_pPixelShader ) g_pPixelShader->Release();
    if( g_pRenderTargetView ) g_pRenderTargetView->Release();
    if( g_pSwapChain ) g_pSwapChain->Release();
    if( g_pImmediateContext ) g_pImmediateContext->Release();
    if( g_pd3dDevice ) g_pd3dDevice->Release();
}

窗口过程函数:

// Called every time the application receives a message
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    // 该结构体包含了某应用程序用来绘制它所拥有的窗口客户区所需要的信息。
    PAINTSTRUCT ps;
    HDC hdc;

    switch( message )
    {
        // 这个消息在Windows程序设计中是很重要的。当窗口显示区域的一部分显示内容或者全部变为"无效",以致于必须"更新画面"时,将由这个消息通知程序。
        case WM_PAINT:
            // 为指定窗口进行绘图工作的准备,并用将和绘图有关的信息填充到一个PAINTSTRUCT结构中。
            hdc = BeginPaint( hWnd, &ps );
            EndPaint( hWnd, &ps );
            break;

        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;

        default:
            // 调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理。该函数确保每一个消息得到处理。
            return DefWindowProc( hWnd, message, wParam, lParam );
    }

    return 0;
}

渲染函数:

// Render a frame
void Render()
{
    // 清空后台缓冲区
    // Clear the back buffer 
    // 设置清空颜色
    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red,green,blue,alpha
    g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, ClearColor );

    // 渲染一个三角形
    // Render a triangle
    // 通过设备上下文接口设置顶点着色器
    g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
    // 通过设备上下文接口设置像素着色器
    g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
    // 完成绘制
    g_pImmediateContext->Draw( 3, 0 );

    // 将渲染到后台缓冲区中的信息展现到前台缓冲区
    // Present the information rendered to the back buffer to the front buffer (the screen)
    g_pSwapChain->Present( 0, 0 );
}

我们快速回顾一遍整个程序的工作

程序入口点函数wWinMain:
->初始化窗口InitWindow
->初始化设备InitDevice
->进入消息循环:
    ->收到消息,则对消息进行处理,同时调用窗口过程函数
    ->没有消息,则进行渲染
->清除所有设备CleanupDevice
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值