Posts Tagged ‘directx’
Rendering animated GIF file
gif file ( http://en.wikipedia.org/wiki/Graphics_Interchange_Format ) is very popular format , you can share funny animation, emotion, a splash for ads, etc. All web browser support this format. do you interested in how game or application (non-web) render animated gif ? . here my experiment result :
( set video quality to 480p )
info :
rendering : DirectX 11
language : c/c++
GIF decoder : libnsgif
Recent spare time projects
I have been working on these projects in my spare time quite while ( like I work on it when I want work on it :p )., but recently I’m disappointed with my progress ( apparently I’m busy and have difficulty when creating graphics assets by myself ). so I decided to upload source code to google code in case I’m interested again next time .There are 2 projects :
[1] unknown project 1. very simple game, almost done. keyword : C/C++,DirectX, Desktop App,Windows Phone 8
home project : https://code.google.com/p/my-fifteen-puzzle-dx/
svn link : https://my-fifteen-puzzle-dx.googlecode.com/svn/trunk
[2] unknown project 2 . also very simple game ( I like simple thing ). puzzle. gameplay complete. keyword : C/C++,DirectX, Desktop App, Windows Phone 8.
home project : https://code.google.com/p/proximity-game-clone2-dx/
svn link : https://proximity-game-clone2-dx.googlecode.com/svn/trunk
both of them actually same app I had made before . I rewrite again these projects using entirely new c/c++ code and using DirectX as graphics API. I also implemented some design pattern there. In case you are interested , check it out 🙂
[3] on directx 11 : load 3D model from file
di project sebelumnya saya hanya menggambar 3d kubus. sangat menarik jika program bisa me-load model 3D yang dibuat oleh 3D editor. format paling populer untuk coba-coba tentu adalah wavefront obj 🙂 . File .obj ini hanya bisa untuk static 3d model, tidak mendukung animasi. Dan biasanya ada 1 file pasangan tambahan untuk setiap .obj yaitu .mtl. File .mtl dimaksudkan untuk menyimpan material ( konstanta pencahayaan , seperti diffuse, spekular ) . namun .mtl file ini optional. File .obj sebenarnya adalah text file. terdapat 2 kata disini “3D model” & “text file”, dan pasti yang terbayang adalah parsing yang lamaaaa . dan memang iya. parsingnya lama. untuk mengakali ini , .obj diubah ke .vbo ( ada orang yang sudah buat tool converter .obj to .vbo . .vbo apa itu?, .vbo sebenarnya adalah versi binary dari .obj, sehingga tidak perlu ada proses parsing waktu load object. 1 fungsi tambahan LoadModel_VBO, dan saya mengubah informasi vertex menjadi :
DirectX::XMFLOAT3 position;
DirectX::XMFLOAT3 normal;
DirectX::XMFLOAT2 texcoord;
fungsi load VBO :
void LoadModel_VBO( unsigned char* meshData, ID3D11Buffer** vertexBuffer,ID3D11Buffer** indexBuffer,int& vertexCount,int& indexCount) {
// The first 4 bytes of the BasicMesh format define the number of vertices in the mesh.
int numVertices = *reinterpret_cast<int*>(meshData);
// The following 4 bytes define the number of indices in the mesh.
int numIndices = *reinterpret_cast<int*>(meshData + sizeof(int));
// The next segment of the BasicMesh format contains the vertices of the mesh.
vertex_type* vertices = reinterpret_cast<vertex_type*>(meshData + sizeof(int) * 2);
// The last segment of the BasicMesh format contains the indices of the mesh.
unsigned short* indices = reinterpret_cast<unsigned short*>(meshData + sizeof(int) * 2 + sizeof(vertex_type) * numVertices);
// Create the vertex and index buffers with the mesh data.
D3D11_SUBRESOURCE_DATA vertexBufferData = {0};
vertexBufferData.pSysMem = vertices;
vertexBufferData.SysMemPitch = 0;
vertexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC vertexBufferDesc(numVertices * sizeof(vertex_type), D3D11_BIND_VERTEX_BUFFER);
HRESULT hr = m_Device->CreateBuffer(
&vertexBufferDesc,
&vertexBufferData,
vertexBuffer
);
assert( hr==S_OK );
D3D11_SUBRESOURCE_DATA indexBufferData = {0};
indexBufferData.pSysMem = indices;
indexBufferData.SysMemPitch = 0;
indexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC indexBufferDesc(numIndices * sizeof(unsigned short), D3D11_BIND_INDEX_BUFFER);
m_Device->CreateBuffer(
&indexBufferDesc,
&indexBufferData,
indexBuffer
);
assert( hr==S_OK );
vertexCount = numVertices;
indexCount = numIndices;
}
output program ( saya me-load utah teapot –yang terkenal itu ) :
full source code & project ( vs 2012 desktop ) . ( xedi_on_directx11___3___from___N.vcxproj )
svn checkout : https://xedi-on-directx-11.googlecode.com/svn/trunk
project home : http://code.google.com/p/xedi-on-directx-11/
// edi ermawan// yogyakarta , 30122013
[2] on directx 11 : sending data to shader
Bagaimana mengirim data dari code CPU ( c++ code ) ke code GPU ( hlsl ) ?. Di program sebelumnya, beberapa data yang di kirim ke shader :
- vertex dan index , direpresentasikan dengan D3D11Buffer , di set ke shader dengan IASetVertexBuffers, dan IASetIndexBuffers. prefix IA : buffer ini di set ke input assembler stage dan dapat diakses di VS .
- model, view, projection matrix, direpresentasikan dengan D3D11Buffer, di set ke shader dengan VSSetConstantBuffers. prefix VS,karena buffer ini akan dipakai sebagai global variable di vertex shader .
- texture, berupa shader resource view, di set ke shader dengan PSSetShaderResources. prefix PS, texture hanya dipakai di pixel shader stage.
model, view projection matrik dibuat dengan bind flag D3D11_BIND_CONSTANT_BUFFER . mvp disini nilainya tidak konstant, tapi berubah-ubah per-frame. lalu kenapa bind flag nya ‘constant buffer’?, hal ini yang membuat saya bertanya diawal2. “constant buffer” disini, dimaksudkan nilainya tetap konstant per 1 proses draw command. namun di draw command selanjutnya bisa berubah. Jika kita ingin memiliki variable yang “semacam” mvp matrix ( berubah-ubah per-frame, dan dapat diakses di shader –vs,ps) , maka kita harus membuat constant buffer semacam ini. sebagai percobaan yang bisa dilihat hasilnya langsung, saya ingin mengirim data ke pixel shader untuk mengubah saturation-desaturation dari texture kubus di program sebelumnya. di c++ code saya perlu struct untuk meng-hold data ini :
struct color_constantbuffer
{
DirectX::XMFLOAT4 saturation;
DirectX::XMFLOAT4 luminance;
};
sedangkan di pixel shader, saya perlu membuat constant buffer, dengan kata kunci cbuffer :
cbuffer ColorConstantBuffer
{
float4 saturation;
float4 luminance;
};
next step, perlu dibuat d3dbuffer untuk menyimpan data : ( m_ColorConstantBuffer adalah ID3D11Buffer* )
D3D11_BUFFER_DESC ColorConstBufferDesc;
ColorConstBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
ColorConstBufferDesc.ByteWidth = sizeof(color_constantbuffer);
ColorConstBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
ColorConstBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
ColorConstBufferDesc.MiscFlags = 0;
ColorConstBufferDesc.StructureByteStride = 0;
hr = m_Device->CreateBuffer( &ColorConstBufferDesc , NULL , &m_ColorConstantBuffer );
dan untuk memberi tahu gpu, kalau buffer ini akan dipakai di pixel shader stage , perlu di set dengan command :
m_DevContext->PSSetConstantBuffers( 0,1,&m_ColorConstantBuffer);
lalu bagaimana cara meng-update color constant buffer ini ?.Untuk mvp constant buffer dipakai UpdateSubresource. Cara lain adalah menggunakan fungsi Map/Unmap . Bedanya dengan UpdateSubresource, Map/Unamp, bisa read-write data ke gpu, sedangkan UpdateSubresource hanya write saja. meng-update color constant buffer dengan Map/Unmap :
D3D11_MAPPED_SUBRESOURCE mappedResource;
color_constantbuffer* colvalue;
HRESULT hr = m_DevContext->Map(m_ColorConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
assert( hr == S_OK );
// get ptr data
colvalue = (color_constantbuffer*)mappedResource.pData;
// set data
colvalue->luminance = DirectX::XMFLOAT4( ); // <— set new value here
colvalue->saturation = DirectX::XMFLOAT4( ); // <— set new value here
// Unlock the constant buffer.
m_DevContext->Unmap(m_ColorConstantBuffer, 0);
di pixel shader, variabel luminance&saturation dipakai menghitung saturaion/desaturation. ( Simple_PS_02.hlsl )
float4 main(PixelShaderInput input) : SV_TARGET
{
// PixelShaderInput.color input doesn’t used in this shader
float4 texColorOut;
// Sample the pixel color from the texture using the sampler at this texture coordinate location.
texColorOut = shaderTexture.Sample(SampleType, input.tex);
float3 luminanceVal = dot( texColorOut, float3(luminance.x,luminance.y,luminance.z));
float4 finalCol = float4( lerp( luminanceVal , texColorOut, saturation ),1.0f);
finalCol.z = texColorOut.z;
return finalCol;
}
note : rumus menghitung saturation/desaturation , nemu di SINI
agar lebih interaktif, di percobaan ini saya menambahkan input untuk user melalui keyboard yang memungkinkan user mengubah saturation dan luminance.
tombol 1-4 : saturation
tombol 5-8: luminance
hasil akhir program percobaan ini: menggambar kubus, dimana warna texture bisa diubah-ubah warnanya dengan mengubah saturation. input lain :
u-i : pitch
o-p: roll
k-l : yaw
n-m : zoom in/out
screenshoot output program (klik gambar untuk memperbesar *) :
full source code & project ( vs 2012 desktop ) . ( xedi_on_directx11___2___from___N.vcxproj )
svn checkout : https://xedi-on-directx-11.googlecode.com/svn/trunk
project home : http://code.google.com/p/xedi-on-directx-11/
// edie // nganjuk , 27122013
[1] on directx 11 : texturing
Di program sebelumnya informasi gambar/ vertex data di-representasikan dengan data struct dibawah ini : (vertex_type.hpp)
struct vertex_type
{
DirectX::XMFLOAT3 position;
DirectX::XMFLOAT3 color;
};
struct ini ber-asosiasi dengan shader code : ( Simple_VS.hlsl )
struct VertexShaderInput
{
float3 pos : POSITION;
float3 color : COLOR0;
};
dengan sedikit modifikasi, kita bisa menambahkan texture ke vertex data untuk kubus :
|
vertex_type.hpp |
Simple_VS.hlsl |
Simple_PS.hlsl |
| structvertex_type{DirectX::XMFLOAT3 position;DirectX::XMFLOAT3 color;DirectX::XMFLOAT2 texcoord; // ← added
}; |
struct VertexShaderInput{float3 pos : POSITION;float3 color : COLOR0;float2 tex : TEXCOORD0;// ← added
};
|
struct PixelShaderInput{float4 pos : SV_POSITION;float3 color : COLOR0;float2 tex:TEXCOORD0;//← added
}; |
Karena informasi vertex berubah, data vertex juga harus diubah, program sekarang harus mengirim : position (float3), color(float3), dan texture coordinate(float2) ke GPU .position adalah jelas koordinat x,y,z di space 3d, color adalah r,g,b di sini, sedangkan texture coordinate, bisa dijelaskan dengan gambar sebagai berikut :
koordinat front face cube :
{XMFLOAT3(-1.0f, -1.0f, -1.0f),XMFLOAT3(0.0f, 0.0f, 0.0f), XMFLOAT2(0.0f, 1.0f)},
{XMFLOAT3(-1.0f, 1.0f, -1.0f),XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(0.0f, 0.0f)},
{XMFLOAT3( 1.0f, 1.0f, -1.0f),XMFLOAT3(1.0f, 0.0f, 0.0f), XMFLOAT2(1.0f, 0.0f)},
{XMFLOAT3( 1.0f, -1.0f, -1.0f),XMFLOAT3(0.0f, 0.0f, 1.0f), XMFLOAT2(1.0f, 1.0f)},
dari gambar, texture akan menutup triangle di koordinat yang bersesuaian.
Langkah selanjutnya adalah mengubah input layout, untuk memberi tahu GPU kalau aplikasi akan mengirim layout data seperti ini :
D3D11_INPUT_ELEMENT_DESC inputVertexDesc[3]; // position , color, texture coord inputVertexDesc[0].SemanticName = "POSITION"; inputVertexDesc[0].SemanticIndex = 0; inputVertexDesc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT; inputVertexDesc[0].InputSlot = 0; inputVertexDesc[0].AlignedByteOffset = 0; inputVertexDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; inputVertexDesc[0].InstanceDataStepRate = 0; inputVertexDesc[1].SemanticName = "COLOR"; inputVertexDesc[1].SemanticIndex = 0; inputVertexDesc[1].Format = DXGI_FORMAT_R32G32B32_FLOAT; inputVertexDesc[1].InputSlot = 0; inputVertexDesc[1].AlignedByteOffset = 12; //D3D11_APPEND_ALIGNED_ELEMENT; inputVertexDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; inputVertexDesc[1].InstanceDataStepRate = 0; inputVertexDesc[2].SemanticName = "TEXCOORD"; // added inputVertexDesc[2].SemanticIndex = 0; inputVertexDesc[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; inputVertexDesc[2].InputSlot = 0; inputVertexDesc[2].AlignedByteOffset =24; //D3D11_APPEND_ALIGNED_ELEMENT; inputVertexDesc[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; inputVertexDesc[2].InstanceDataStepRate = 0; int numElement = sizeof( inputVertexDesc ) / sizeof ( inputVertexDesc[0] ); hr = m_Device->CreateInputLayout ( inputVertexDesc, numElement , vs_ba , vs_ba_len , &m_InputLayout );
step selanjutnya kita perlu menyiapkan data texture. Di project saya menambahkan DDSTextureLoader class ( class helper untuk me-load texture dari file ).
CreateDDSTextureFromFile( m_Device , L”../data/textures/texture_01.DDS”, nullptr, &m_TextureShaderResView, MAXSIZE_T);
dan data texture ini kita kirim ke gpu sebelum eksekusi gambar terjadi :
m_DevContext->PSSetShaderResources(0, 1, &m_TextureShaderResView);
m_DevContext->DrawIndexed(36, 0, 0);
Hasil eksekusi program :
full source code & project ( vs 2012 desktop ) . ( xedi_on_directx11___1___from___N.vcxproj )
svn checkout : https://xedi-on-directx-11.googlecode.com/svn/trunk
project home : http://code.google.com/p/xedi-on-directx-11/
// edie // nganjuk , 26122013




