LightShaderClass.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. using System;
  2. using System.Threading.Tasks;
  3. using System.Windows.Forms;
  4. using SlimDX;
  5. using SlimDX.D3DCompiler;
  6. using SlimDX.Direct3D11;
  7. using SlimDX.DXGI;
  8. using SlimDX.Windows;
  9. using Device = SlimDX.Direct3D11.Device;
  10. using Resource = SlimDX.Direct3D11.Resource;
  11. using Buffer = SlimDX.Direct3D11.Buffer;
  12. namespace EQ2ModelViewer
  13. {
  14. public class LightShaderClass
  15. {
  16. private struct MatrixBufferType
  17. {
  18. public Matrix world;
  19. public Matrix view;
  20. public Matrix projection;
  21. }
  22. private struct CameraBufferType
  23. {
  24. public Vector3 cameraPosition;
  25. public float padding;
  26. }
  27. private struct LightBufferType
  28. {
  29. public Vector4 ambientColor;
  30. public Vector4 diffuseColor;
  31. public Vector3 lightDirection;
  32. public float specularPower;
  33. public Vector4 specularColor;
  34. }
  35. private VertexShader m_VertexShader;
  36. private PixelShader m_PixelShader;
  37. private InputLayout m_Layout;
  38. private Buffer m_MatrixBuffer;
  39. private SamplerState m_SamplerState;
  40. private Buffer m_CameraBuffer;
  41. private Buffer m_LightBuffer;
  42. public bool Initialize(Device device)
  43. {
  44. return InitializeShader(device, "Light.vs", "Light.ps");
  45. }
  46. private bool InitializeShader(Device device, string vertexShader, string pixelShader)
  47. {
  48. ShaderSignature inputSignature;
  49. string error;
  50. // load and compile the vertex shader
  51. using (var bytecode = ShaderBytecode.CompileFromFile(vertexShader, "LightVertexShader", "vs_5_0", ShaderFlags.EnableStrictness, EffectFlags.None, null, null, out error))
  52. {
  53. inputSignature = ShaderSignature.GetInputSignature(bytecode);
  54. m_VertexShader = new VertexShader(device, bytecode);
  55. }
  56. if (m_VertexShader == null)
  57. {
  58. Console.WriteLine("InitializeShader: Error creating vertex shader: " + error);
  59. return false;
  60. }
  61. // load and compile the pixel shader
  62. using (var bytecode = ShaderBytecode.CompileFromFile(pixelShader, "LightPixelShader", "ps_5_0", ShaderFlags.EnableStrictness, EffectFlags.None, null, null, out error))
  63. m_PixelShader = new PixelShader(device, bytecode);
  64. if (m_PixelShader == null)
  65. {
  66. Console.WriteLine("InitializeShader: Error creating pixel shader: " + error);
  67. return false;
  68. }
  69. var elements = new[] {
  70. new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0, InputClassification.PerVertexData, 0),
  71. new InputElement("TEXCOORD", 0, Format.R32G32_Float, -1, 0, InputClassification.PerVertexData, 0),
  72. new InputElement("NORMAL", 0, Format.R32G32B32_Float, -1, 0, InputClassification.PerVertexData, 0) };
  73. m_Layout = new InputLayout(device, inputSignature, elements);
  74. m_MatrixBuffer = new Buffer(device, System.Runtime.InteropServices.Marshal.SizeOf(typeof(MatrixBufferType)), ResourceUsage.Dynamic, BindFlags.ConstantBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0);
  75. if (m_MatrixBuffer == null)
  76. {
  77. Console.WriteLine("InitializeShader: Unable to create the matrix buffer.");
  78. return false;
  79. }
  80. SamplerDescription samplerDesc = new SamplerDescription();
  81. samplerDesc.Filter = Filter.MinMagMipLinear;
  82. samplerDesc.AddressU = TextureAddressMode.Wrap;
  83. samplerDesc.AddressV = TextureAddressMode.Wrap;
  84. samplerDesc.AddressW = TextureAddressMode.Wrap;
  85. samplerDesc.MipLodBias = 0.0f;
  86. samplerDesc.MaximumAnisotropy = 1;
  87. samplerDesc.ComparisonFunction = Comparison.Always;
  88. samplerDesc.BorderColor = new Color4(0.0f, 0.0f, 0.0f, 0.0f);
  89. samplerDesc.MinimumLod = 0;
  90. samplerDesc.MaximumLod = 3.402823466e+38f; // from d3d11.h, #define D3D11_FLOAT32_MAX ( 3.402823466e+38f )
  91. m_SamplerState = SamplerState.FromDescription(device, samplerDesc);
  92. if (m_SamplerState == null)
  93. {
  94. Console.WriteLine("InitializeShader: Unable to create the sampler state.");
  95. return false;
  96. }
  97. m_CameraBuffer = new Buffer(device, System.Runtime.InteropServices.Marshal.SizeOf(typeof(CameraBufferType)), ResourceUsage.Dynamic, BindFlags.ConstantBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0);
  98. if (m_CameraBuffer == null)
  99. {
  100. Console.WriteLine("InitializeShader: Unable to create the camera buffer.");
  101. return false;
  102. }
  103. m_LightBuffer = new Buffer(device, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightBufferType)), ResourceUsage.Dynamic, BindFlags.ConstantBuffer, CpuAccessFlags.Write, ResourceOptionFlags.None, 0);
  104. if (m_LightBuffer == null)
  105. {
  106. Console.WriteLine("InitializeShader: Unable to create the light buffer.");
  107. return false;
  108. }
  109. return true;
  110. }
  111. public void ShutDown()
  112. {
  113. m_VertexShader.Dispose();
  114. m_PixelShader.Dispose();
  115. m_Layout.Dispose();
  116. m_MatrixBuffer.Dispose();
  117. m_SamplerState.Dispose();
  118. m_CameraBuffer.Dispose();
  119. m_LightBuffer.Dispose();
  120. }
  121. private bool SetShaderParameters(DeviceContext context, Matrix worldMatrix, Matrix viewMatrix, Matrix projectionMatrix, ShaderResourceView texture, Vector3 lightDirection, Vector4 ambientColor, Vector4 diffuseColor, Vector3 cameraPosition, Vector4 specularColor, float specularPower)
  122. {
  123. Matrix.Transpose(ref worldMatrix, out worldMatrix);
  124. Matrix.Transpose(ref viewMatrix, out viewMatrix);
  125. Matrix.Transpose(ref projectionMatrix, out projectionMatrix);
  126. var mappedResource = context.MapSubresource(m_MatrixBuffer, 0, MapMode.WriteDiscard, SlimDX.Direct3D11.MapFlags.None);
  127. MatrixBufferType data = new MatrixBufferType();
  128. data.world = worldMatrix;
  129. data.view = viewMatrix;
  130. data.projection = projectionMatrix;
  131. mappedResource.Data.Write<MatrixBufferType>(data);
  132. context.UnmapSubresource(m_MatrixBuffer, 0);
  133. context.VertexShader.SetConstantBuffer(m_MatrixBuffer, 0);
  134. context.PixelShader.SetShaderResource(texture, 0);
  135. mappedResource = context.MapSubresource(m_CameraBuffer, 0, MapMode.WriteDiscard, SlimDX.Direct3D11.MapFlags.None);
  136. CameraBufferType data2 = new CameraBufferType();
  137. data2.cameraPosition = cameraPosition;
  138. data2.padding = 0.0f;
  139. mappedResource.Data.Write<CameraBufferType>(data2);
  140. context.UnmapSubresource(m_CameraBuffer, 0);
  141. context.VertexShader.SetConstantBuffer(m_CameraBuffer, 1);
  142. mappedResource = context.MapSubresource(m_LightBuffer, 0, MapMode.WriteDiscard, SlimDX.Direct3D11.MapFlags.None);
  143. LightBufferType data3 = new LightBufferType();
  144. data3.ambientColor = ambientColor;
  145. data3.diffuseColor = diffuseColor;
  146. data3.lightDirection = lightDirection;
  147. data3.specularColor = specularColor;
  148. data3.specularPower = specularPower;
  149. mappedResource.Data.Write<LightBufferType>(data3);
  150. context.UnmapSubresource(m_LightBuffer, 0);
  151. context.PixelShader.SetConstantBuffer(m_LightBuffer, 0);
  152. return true;
  153. }
  154. public bool Render(DeviceContext context, int indexCount, Matrix worldMatrix, Matrix viewMatrix, Matrix projectionMatrix, ShaderResourceView texture, Vector3 lightDirection, Vector4 ambientColor, Vector4 diffuseColor, Vector3 cameraPosition, Vector4 specularColor, float specularPower)
  155. {
  156. if (!SetShaderParameters(context, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, ambientColor, diffuseColor, cameraPosition, specularColor, specularPower))
  157. return false;
  158. RenderShader(context, indexCount);
  159. return true;
  160. }
  161. private void RenderShader(DeviceContext context, int indexCount)
  162. {
  163. // Set the vertex input layout
  164. context.InputAssembler.InputLayout = m_Layout;
  165. // Set the vertex and pixel shaders that will be used to render
  166. context.VertexShader.Set(m_VertexShader);
  167. context.PixelShader.Set(m_PixelShader);
  168. // Set the sampler state in the pixel shader
  169. context.PixelShader.SetSampler(m_SamplerState, 0);
  170. // Render
  171. context.DrawIndexed(indexCount, 0, 0);
  172. }
  173. }
  174. }