艾莉兒:主人又在研究奇怪的東西了……無聊研究一下Direct3D 11,前作Cyber Sprite是用OpenGL,把引擎裡的功能用D3D11寫一次看看。
選擇11是因為Windows Phone使用的Direct3D版本是11,假如以後要寫Windows Phone程式可以先鋪路,另外Cyber Sprite 2預定最低支援Windows 7,能跑D3D11是Windows 7的系統需求所以不怕玩家的電腦不能跑。
D3D10開始把D3D9以前的做法整個改掉,初始化很冗長,從零做到最低限能動有很多東西要準備,應該是眾所周知的事吧。
參考這個網站,還有之前買的一本書
http://www.directxtutorial.com/LessonList.aspx?listid=11雖然中間以後的篇章要付費觀看,不過前半就很夠用了
當然要先建個視窗才能在上面用D3D畫圖,用用過無數次的WNDCLASS、CreateWindow等等。
再來怎麼讓D3D11動作呢?
艾莉兒:我看看……,第一步要建立這四個物件。
ID3D11Device IDXGISwapChain ID3D11DeviceContext ID3D11RenderTargetView |
最開始是D3D11CreateDeviceAndSwapChain建立前三個,然後用device->CreateRenderTargetView建RenderTargetView,…………寫好了
艾莉兒:再來要準備的東西有……
艾莉兒:首先是shader隨便寫個vertex shader和pixel shader,先不做坐標轉換和貼圖,先讓畫面上有東西出現再說。
載入方法嘛,這次寫在另一個檔案用D3DX11CompileFromFile載入,以後在正式作品用再叫鈷寶處理。
struct ParticleIn{ float2 pos:POSITION; int2 texCoord:TEXCOORD; float4 color:COLOR; };
struct VsOut{ float4 pos:SV_POSITION; float2 texCoord:TEXCOORD; float4 color:COLOR; };
void particleVS(in ParticleIn IN,out VsOut OUT){ OUT.pos=float4(IN.pos,0,1); OUT.color=float4(0,1,1,1); OUT.texCoord=IN.texCoord; }
float4 flatPS(VsOut IN):SV_TARGET{ return IN.color; } |
艾莉兒:再來頂點位置,D3D11沒有像glVertexPointer和glDrawArrays的東西,一定要用buffer。不能畫圖同時上傳頂點資料,要建立一個buffer物件→填入資料→呼叫context->IASetVertexBuffers套用
仿照引擎裡particle的格式,隨更弄個測試資料
struct ParticleVertex{ float pos[2]; int16_t texCoord[2]; uint32_t color; }; const ParticleVertex Vertices[]={ {{-1,0},{0,0},0xffffffff}, {{0,1},{0,1},0xffffffff}, {{1,0},{1,1},0xffffffff}, }; |
雖然有texCoord和color的欄位,但這一版還沒用到
艾莉兒:還要定義一個input layout還要弄這個東西哦,把C裡的頂點struct對應到shader裡的struct
const D3D11_INPUT_ELEMENT_DESC particleLayoutDesc[] = { {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"TEXCOORD", 0, DXGI_FORMAT_R16G16_SINT , 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0}, {"COLOR", 0, DXGI_FORMAT_B8G8R8A8_UNORM, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}, }; |
然後在更新frame的函式裡,呼叫IASetInputLayout、VSSetShader、PSSetShader、IASetVertexBuffers等一個個套用剛剛準備的物件,最後用context->Draw畫出來。
第一階段的成果,能在畫面上秀出東西了
坐標確定無誤(沒設轉換矩陣的話,整個畫面的XY坐標範圍是-1~1),顏色也是shader裡指定的float4(0,1,1,1)
除了一開始的4個系統物件以外,做到這裡要建立的物件
ID3D11Buffer* vertexBuffer; ID3D11VertexShader* particleVS; ID3D11PixelShader* flatPS; ID3D11InputLayout* particleLayout; |
艾莉兒:嗯,會把我改造,讓我以後在Windows上用Direct3D嗎?
總覺得顯卡廠商的OpenGL驅動程式都沒好好寫,讓我不能發揮全部實力,想用Direct3D試試看。(這是試過幾個顯卡,也試過同一顯卡在Windows和Linux下的差異的感覺)
先繼續研究一下再說吧,D3D11和OpenGL差很多,要讓引擎同時支援兩者很費工。
這次做到最低限能動,接下來把其他功能一個一個加上去,待續。