[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 *) :

cube_rot_frog

full source code & project ( vs 2012 desktop ) . ( xedi_on_directx112from___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

comments powered by Disqus