Xedi.Xermawan's Blog

personal-technical blog

Posts Tagged ‘directx 11

[2] on directx 11 : sending data to shader

leave a comment »

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_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

Written by XediXermawan

December 27, 2013 at 4:50 pm

Posted in C/C++ Diary, DirectX

Tagged with ,