[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