3D图形学编程基础-基于Direct3D11-学习记录(一)初始化DX设备,实现立方体绘制

来源:互联网 发布:网络推广的主要方法 编辑:程序博客网 时间:2024/05/05 12:36

第一次写博客这个东西,平时自己学习的时候记录的东西都是纸质的,查找不太方便,而且由于自己得不少知识学习都来自CSDN。所以在这里做一个我自学的记录!

由于第一次学习Directx,记录的很多东西都是自己简单了解到的。可能不全,甚至可能不对,先记录下,以后修改!

基于VisualC++,Directx学习记录正式开始:

一:基础概念的了解

1.Direct3D的定义:是微软公司创建的多媒体编程接口。由C++实现,被用于Windows,XBOX,XBOX360电子游戏的开发,并且只支持这些平台

2.必要的工具及开发环境:需要一个最新的DirectX SDK。和visual studio (貌似在下载安装VS的时候会自动下载下Directx SDK)SDK下载的文件夹中有个Simples文件,里面有不少的简单代码供于学习

二:初始化Direct3D设备

Direct3D使用之前需要创建一个设备,通过这个设备来调用Direct API;

在Direct3D中设备被分成了两个部分:1.Device (用来创建资源)  2.Devicecontext (用来执行渲染操作) 

初始化Direct3D要实现三个目的:1.创建设备。2.创建交换链。3。创建立即执行上下文(context)。       知识补充:1设备,很简单,调用directX API的。2.交换链。交换链上实际保存着两个缓存(buffer)。一个前台缓存,一个后台缓存。缓存上存储着绘制好的图像信息,前台缓存显示在屏幕上时,后台缓存绘制下一个图像信息(如果只有一个缓存的话,切换界面时绘制图画会导致屏幕闪烁)。3,立即执行上下文。用来直接向驱动发送渲染信息。上下文分为两种 立即执行上下文和延迟执行上下文(一般用于分线程);      整体来说。设备是管理资源,交换链是显示资源,上下文是处理资源的(多好理解);

初始化Direct3D的4个步骤:1,填写DXGI_SWAP_CHAIN_DESC(交换链结构)

  2,用D3D11CreateDeviceAndSwapChain函数和1中的结构体,创建ID3D11Device(设备),IDXGISwapChain(交换链)和ID3D11DeviceContext;

3.创建渲染视图ID3D11RenderTargetView并将其绑定至管线   (为了让后台缓存可以被渲染)

4,设置视口(一个在windows窗口中用来显示Direct的地方)

三.下面开始简单的代码示例

#include <windows.h> //要用到windows环境和windows窗口

#include <d3d11.h> //用到D3D的API

#include <d3dx11.h> //我电脑中D3D的头文件和库文件位置是C:\Program Files (x86)\Windows Kits\8.1\Include\um

#include <d3dcompiler.h> //应该是着色器的接口函数用到此头文件

#include <xnamath.h> //XNA的数学库

#include "resource.h" //图片资源文件


struct SimpleVertex //定义一个顶点数据类型,这里面只写了位置和颜色,实际上还可以包含很多例如顶点法向量,纹理坐标,镜面反射颜色等

{

XMFLOAT3 Pos;//由三个单精度浮点数组成的顶点的坐标,float4的第四个坐标是齐次坐标

XMFLOAT4 Color;//由4个单精度浮点数组成的颜色坐标,前三位是RGB值,最后一个是Aplha透明度

};


struct ConstantBuffer //世界坐标向视图坐标转换的数据保存矩阵,世界坐标是三维的,想在二维屏幕上显示就需要转换。绘制三维物体都需要这个

{

AMMATRIX wWorld; //保存物体的三维实际坐标

AMMATRIX wView;

AMMATRIX mProjection;

};


//定义了一些全局变量

HINSTANCE              g_hInst = NULL;//window窗口用到
HWND                      g_hWnd = NULL;
D3D_DRIVER_TYPE          g_driverType = D3D_DRIVER_TYPE_NULL;//驱动器类型(D3D的执行位置)
D3D_FEATURE_LEVEL        g_featureLevel = D3D_FEATURE_LEVEL_11_0;//DX版本,这里是DX11
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;//顶点缓存区
ID3D11Buffer*  g_pIndexBuffer = NULL;//索引缓存区
ID3D11Buffer*  g_pConstantBuffer = NULL;//世界转换缓存区
XMMATRIX  g_World;//世界坐标
XMMATRIX  g_View;
XMMATRIX  g_Projection;

HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );//windows窗口创建函数
HRESULT InitDevice(); //设备初始化函数
void CleanupDevice(); //设备清空函数
LRESULT CALLBACK    WndProc( HWND, UINT, WPARAM, LPARAM );//windows窗口回调函数
void Render(); //图形绘制函数


//主函数

int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
    UNREFERENCED_PARAMETER( hPrevInstance );
    UNREFERENCED_PARAMETER( lpCmdLine );


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


    if( FAILED( InitDevice() ) ) //初始化设备
    {
        CleanupDevice();
        return 0;
    }


    // Main message loop
    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;
}

//windows窗口创建函数
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 11 Tutorial 3: Shaders",
                           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;
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
    PAINTSTRUCT ps;
    HDC hdc;


    switch( message )
    {
        case WM_PAINT:
            hdc = BeginPaint( hWnd, &ps );
            EndPaint( hWnd, &ps );
            break;


        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;


        default:
            return DefWindowProc( hWnd, message, wParam, lParam );
    }


    return 0;
}


//着色器创建文件,将着色器和着色器主函数绑定,返回着色器接口

//参数1:着色器文件,由HLSL编写的.fx着色器文件,主函数名字,着色器版本,着色器接口名

HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
    HRESULT hr = S_OK;


    DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
    dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif


    ID3DBlob* pErrorBlob;
    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;
}


//初始化设备,绑定立即执行上下文等等

HRESULT InitDevice()
{
HRESULT hr = S_OK;


RECT rc;
GetClientRect(g_hWnd, &rc);//获取窗口
UINT width = rc.right - rc.left;//获取宽高
UINT height = rc.bottom - rc.top;


UINT createDeviceFlags = 0;//通常为0,当启用调试模式的时候变为DEBUG
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

D3D_DRIVER_TYPE driverTypes[] =//此参数表示D3D工作位置(驱动类型)
{
D3D_DRIVER_TYPE_HARDWARE,//显卡驱动,我们实例选择显卡驱动   (由于是GPC访问,所以需要将资源放置一个特定的资源容器中,即D3D11_BUFFER_DESC缓存)

//以目前的学习内容还不知道为什么需要这个资源缓存,以及其他访问方式的用法
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTypes = ARRAYSIZE(driverTypes);//类型个数


D3D_FEATURE_LEVEL featureLevels[] =//DX版本
{
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;//指定的windows窗口接口
sd.SampleDesc.Count = 1;//多重采样的数据设定,count是计算每个像素前需要采样的个数,
sd.SampleDesc.Quality = 0;//quality是最终的效果,当设置为1,0时表示不需要多重采样
sd.Windowed = TRUE;//是窗口模式还是全屏


//小知识点补充1.D3D11_USAGE资源的使用方法。具体分类有,资源不可被改变,1帧可被改变一次,1帧可被改变多次;CPU,GPU可只读,读写,不可访问等多项具体的设定;

//小知识补充2,多重采样,因为分辨率的问题有的图像在渲染出来会出现锯齿边的情况即走样,多重采样是反走样技术,当分辨率无法提升的情况下,获取周围多个点的颜色信息来确定当前点的颜色。这样增加了运行开销;

for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain(NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext);
//参数一:此函数第一个参数表示适配器类型,NULL表示默认适配器
//参数二:第二个表示D3D的工作位置,在哪个驱动上进行
//参数三:当第二个参数选择的驱动类型是软的的话,此处需要设定光栅化类型。否则设置为NULL
//参数四:选择当前是release还是debug。release时为0,debug时为D3D11_CREATE_DEVICE_DEBUG;
//参数五:DX的版本
//参数六:DX版本个数
//参数七:都让写成这样,然而不知道为什么
//参数八:创建所需要的DXGI_SWAP_CHAIN_DESC类型结构体
//参数9,10,11,12:都为创建好的接口,分别是交换链接口,设备接口,DX版本和立即执行上下文接口;
if (SUCCEEDED(hr))
break;
}
if (FAILED(hr))
return hr;


// 为了让后台缓存可以渲染目标,需要创建一个渲染目标视图
ID3D11Texture2D* pBackBuffer = NULL;
hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
if (FAILED(hr))
return hr;

hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_pRenderTargetView);//null可以选择D3D11_RENDERTARGETVIEW_DESC,
pBackBuffer->Release();
if (FAILED(hr))
return hr;

//此函数将渲染目标绑定到立即执行上下文上
g_pImmediateContext->OMSetRenderTargets(1, &g_pRenderTargetView, NULL);


// 创建视口  在windows窗口中显示一个Direct的显示口
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)width;//视口的大小
vp.Height = (FLOAT)height;
vp.MinDepth = 0.0f;//深度缓存的值  一般填0和1
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;//视口左上角对应位置
vp.TopLeftY = 0;
g_pImmediateContext->RSSetViewports(1, &vp);


// Compile the vertex shader通过读取着色器文件来生成顶点着色器接口
// .fx是着色器文件,VS是着色器主函数,vs_4_0是顶点着色器版本,ID3DBlob是着色器接口
ID3DBlob* pVSBlob = NULL;//着色器接口类型
hr = CompileShaderFromFile(L"Tutorial03.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用一下数组创建一个对象来描述输入顶点的布局信息
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },//顶点坐标的描述信息
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }//顶点颜色属性的描述,
};
UINT numElements = ARRAYSIZE(layout);


// Create the input layout 利用着色器和布局信息创建顶点布局对象
hr = g_pd3dDevice->CreateInputLayout(layout, numElements, pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(), &g_pVertexLayout);
pVSBlob->Release();//接口使用完成  释放
if (FAILED(hr))
return hr;


// Set the input layout为立即执行上下文来设置定点布局对象
g_pImmediateContext->IASetInputLayout(g_pVertexLayout);


// Compile the pixel shader创建像素着色器接口
ID3DBlob* pPSBlob = NULL;
hr = CompileShaderFromFile(L"Tutorial03.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[] =
{
{ XMFLOAT3(-1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f) },
{ XMFLOAT3(1.0f, 1.0f, -1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f) },
{ XMFLOAT3(1.0f, 1.0f, 1.0f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f) },
{ XMFLOAT3(-1.0f, 1.0f, 1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f) },
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f) },
{ XMFLOAT3(1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f) },
{ XMFLOAT3(1.0f, -1.0f, 1.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f) },
{ XMFLOAT3(-1.0f, -1.0f, 1.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f) },
    };


//这是缓存的结构体

//原始数据必须包装在D3D11_BUFFER_DESC和D3D11_SUBRESOUCE_DATA结构体中
    D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D11_USAGE_DEFAULT;//缓存的使用方式
    bd.ByteWidth = sizeof( SimpleVertex ) * 8;//数据大小
    bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;//数据类型:顶点缓存
bd.CPUAccessFlags = 0;


    D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
    InitData.pSysMem = vertices;


//将顶点缓存绑定至上下文 1.创建缓存
    hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
    if( FAILED( hr ) )
        return hr;

    // Set vertex buffer2.绑定至顶点缓存立即执行上下文
   UINT stride = sizeof( SimpleVertex );
    UINT offset = 0;
    g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );//此函数的前两个参数表示slot的开始数 和个数  ,但是我并不明白slot是什么


//立方体索引缓存
//立方体有8个顶点,顶点缓存描述了每个顶点的信息。索引缓存描述的是顶点的渲染顺序,3个点组成一个三角形,3个三角形组成一个四方形面,6个面组成立方体
WORD indices[] =
{
3, 1, 0,
2, 1, 3,


0, 5, 4,
1, 5, 0,


3, 4, 7,
0, 4, 3,


1, 6, 5,
2, 6, 1,


2, 7, 6,
3, 7, 2,


6, 4, 5,
7, 4, 6,
};


//要创建的索引缓存的结构 自己写的时候从写了一个缓存,不能重写,只能修改
//D3D11_BUFFER_DESC bd1;//这是自己新创建的缓存不对
//ZeroMemory(&bd1, sizeof(bd1));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(WORD)* 36;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;//数据类型:索引缓存
bd.CPUAccessFlags = 0;


//设定用于初始化索引缓存的数据这里也是修改旧的  不用新建
//D3D11_SUBRESOURCE_DATA InitData;
//ZeroMemory(&InitData1, sizeof(InitData1));
//InitData.pSysMem = vertices;
InitData.pSysMem = indices;


//创建索引缓存
hr = g_pd3dDevice->CreateBuffer(&bd, &InitData, &g_pIndexBuffer);
if (FAILED(hr))
return hr;

//绑定至立即执行上下文
g_pImmediateContext->IASetIndexBuffer(g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);


// Set primitive topology//指定图元类型。后面的枚举表示着据算计对图元点的保存方式,,具体方式对应需要查找
//此保存方式为完全保存

//索引缓存的索引方式有很多种,所以此处设置值得时候需要注意,当前索引缓存方式是全部索引

g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

//g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);用一些其他精简索引方式时可能需要改变


//一下内容是用来进行坐标转换的 ,尚未看懂!!!

// Create the constant buffer
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(ConstantBuffer);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = 0;
hr = g_pd3dDevice->CreateBuffer(&bd, NULL, &g_pConstantBuffer);
if (FAILED(hr))
return hr;


// Initialize the world matrix
g_World = XMMatrixIdentity();


//// Initialize the view matrix
XMVECTOR Eye = XMVectorSet(0.0f, 1.0f, -5.0f, 0.0f);
XMVECTOR At = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
g_View = XMMatrixLookAtLH(Eye, At, Up);


// Initialize the projection matrix
g_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV2, width / (FLOAT)height, 0.01f, 100.0f);




    return S_OK;

}


//绘制函数

void Render()
{
// Update our time
static float t = 0.0f;
if (g_driverType == D3D_DRIVER_TYPE_REFERENCE)
{
t += (float)XM_PI * 0.0125f;
}
else
{
static DWORD dwTimeStart = 0;
DWORD dwTimeCur = GetTickCount();
if (dwTimeStart == 0)
dwTimeStart = dwTimeCur;
t = (dwTimeCur - dwTimeStart) / 1000.0f;
}


////
//// Animate the cube
////
g_World = XMMatrixRotationY(t);


    // Clear the back buffer 清空前一帧的显示数据   将视口绘制成以下颜色
    float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red,green,blue,alpha
    g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );


//
// Update variables
//
ConstantBuffer cb;
cb.mWorld = XMMatrixTranspose(g_World);
cb.mView = XMMatrixTranspose(g_View);
cb.mProjection = XMMatrixTranspose(g_Projection);
g_pImmediateContext->UpdateSubresource(g_pConstantBuffer, 0, NULL, &cb, 0, 0);


    // Render a triangle 将着色器绑定到上下文
g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
g_pImmediateContext->VSSetConstantBuffers(0, 1, &g_pConstantBuffer);
g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
g_pImmediateContext->DrawIndexed(36, 0, 0);




    // Present the information rendered to the back buffer to the front buffer (the screen)
    //交换链的价值在次数用到。因为一个屏幕的清屏和渲染操作的话会出现闪屏,这是后就需要交换链了(前后两个缓存屏)
    g_pSwapChain->Present( 0, 0 );
}


void CleanupDevice()
{

//这个清除顺序是需要注意的  不是随便写
if (g_pImmediateContext) g_pImmediateContext->ClearState();


if (g_pConstantBuffer) g_pConstantBuffer->Release();
if (g_pVertexBuffer) g_pVertexBuffer->Release();
if (g_pIndexBuffer) g_pIndexBuffer->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();
}


//少传了一个着色器文件

Tutorial03.fx //此文件是由HLSL高级着色器语言编写的,和C++类似

//常量缓存的定义

cbuffer ConstantBuffer : register(b0)
{
matrix World;
matrix View;
matrix Projection;
};

//结构体的定义
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
};

//--------------------------------------------------------------------------------------
// Vertex Shader 顶点着色器主函数
// 此处是一个立方体的着色器内容,函数内进行了一个三维空间坐标,向屏幕坐标的转换
//--------------------------------------------------------------------------------------
VS_OUTPUT VS(float4 Pos : POSITION,float4 Color : COLOR)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.Pos = mul(Pos, World);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);


output.Color = Color;
//output.Pos = Pos;


return output;
}


//Pixel Shader 像素着色器主函数,仅返回了一个颜色值

float4 PS(VS_OUTPUT input) : SV_Target
{
return input.Color;
}


以上代码是一个立方体的绘制代码,是DX自带的学习代码,自己只是通过学习大概注释了一下

0 0
原创粉丝点击