Khaotic Engine Reborn
Loading...
Searching...
No Matches
refraction_shader_class.cpp
1#include "refraction_shader_class.h"
2
3
4refraction_shader_class::refraction_shader_class()
5{
6 vertex_shader_ = 0;
7 pixel_shader_ = 0;
8 layout_ = 0;
9 matrix_buffer_ = 0;
10 sample_state_ = 0;
11 light_buffer_ = 0;
12 clip_plane_buffer_ = 0;
13}
14
15
16refraction_shader_class::refraction_shader_class(const refraction_shader_class& other)
17{
18}
19
20
21refraction_shader_class::~refraction_shader_class()
22{
23}
24
25
26bool refraction_shader_class::initialize(ID3D11Device* device, HWND hwnd)
27{
28 bool result;
29 wchar_t vsFilename[128];
30 wchar_t psFilename[128];
31 int error;
32
33 // Set the filename of the vertex shader.
34 error = wcscpy_s(vsFilename, 128, L"src/hlsl/refraction.vs");
35 if (error != 0)
36 {
37 return false;
38 }
39
40 // Set the filename of the pixel shader.
41 error = wcscpy_s(psFilename, 128, L"src/hlsl/refraction.ps");
42 if (error != 0)
43 {
44 return false;
45 }
46
47 // initialize the vertex and pixel shaders.
48 result = initialize_shader(device, hwnd, vsFilename, psFilename);
49 if (!result)
50 {
51 return false;
52 }
53
54 return true;
55}
56
57
58void refraction_shader_class::shutdown()
59{
60 // shutdown the vertex and pixel shaders as well as the related objects.
61 shutdown_shader();
62
63 return;
64}
65
66bool refraction_shader_class::render(ID3D11DeviceContext* deviceContext, int indexCount, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
67 ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 ambientColor[], XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 clipPlane)
68{
69 bool result;
70
71
72 // Set the shader parameters that it will use for rendering.
73 result = set_shader_parameters(deviceContext, worldMatrix, viewMatrix, projectionMatrix, texture, lightDirection, ambientColor, diffuseColor, lightPosition, clipPlane);
74 if (!result)
75 {
76 return false;
77 }
78
79 // Now render the prepared buffers with the shader.
80 render_shader(deviceContext, indexCount);
81
82 return true;
83}
84
85
86bool refraction_shader_class::initialize_shader(ID3D11Device* device, HWND hwnd, WCHAR* vsFilename, WCHAR* psFilename)
87{
88 HRESULT result;
89 ID3D10Blob* errorMessage;
90 ID3D10Blob* vertexShaderBuffer;
91 ID3D10Blob* pixelShaderBuffer;
92 D3D11_INPUT_ELEMENT_DESC polygonLayout[3];
93 unsigned int numElements;
94 D3D11_BUFFER_DESC matrixBufferDesc;
95 D3D11_SAMPLER_DESC samplerDesc;
96 D3D11_BUFFER_DESC lightBufferDesc;
97 D3D11_BUFFER_DESC clipPlaneBufferDesc;
98
99
100 // initialize the pointers this function will use to null.
101 errorMessage = 0;
102 vertexShaderBuffer = 0;
103 pixelShaderBuffer = 0;
104
105 // Compile the vertex shader code.
106 result = D3DCompileFromFile(vsFilename, NULL, NULL, "RefractionVertexShader", "vs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0,
107 &vertexShaderBuffer, &errorMessage);
108 if (FAILED(result))
109 {
110 // If the shader failed to compile it should have writen something to the error message.
111 if (errorMessage)
112 {
113 output_shader_error_message(errorMessage, hwnd, vsFilename);
114 }
115 // If there was nothing in the error message then it simply could not find the shader file itself.
116 else
117 {
118 MessageBox(hwnd, vsFilename, L"Missing Shader File", MB_OK);
119 }
120
121 return false;
122 }
123
124 // Compile the pixel shader code.
125 result = D3DCompileFromFile(psFilename, NULL, NULL, "RefractionPixelShader", "ps_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0,
126 &pixelShaderBuffer, &errorMessage);
127 if (FAILED(result))
128 {
129 // If the shader failed to compile it should have writen something to the error message.
130 if (errorMessage)
131 {
132 output_shader_error_message(errorMessage, hwnd, psFilename);
133 }
134 // If there was nothing in the error message then it simply could not find the file itself.
135 else
136 {
137 MessageBox(hwnd, psFilename, L"Missing Shader File", MB_OK);
138 }
139
140 return false;
141 }
142
143 // Create the vertex shader from the buffer.
144 result = device->CreateVertexShader(vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), NULL, &vertex_shader_);
145 if (FAILED(result))
146 {
147 return false;
148 }
149
150 // Create the pixel shader from the buffer.
151 result = device->CreatePixelShader(pixelShaderBuffer->GetBufferPointer(), pixelShaderBuffer->GetBufferSize(), NULL, &pixel_shader_);
152 if (FAILED(result))
153 {
154 return false;
155 }
156
157 // Create the vertex input layout description.
158 polygonLayout[0].SemanticName = "POSITION";
159 polygonLayout[0].SemanticIndex = 0;
160 polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
161 polygonLayout[0].InputSlot = 0;
162 polygonLayout[0].AlignedByteOffset = 0;
163 polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
164 polygonLayout[0].InstanceDataStepRate = 0;
165
166 polygonLayout[1].SemanticName = "TEXCOORD";
167 polygonLayout[1].SemanticIndex = 0;
168 polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
169 polygonLayout[1].InputSlot = 0;
170 polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
171 polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
172 polygonLayout[1].InstanceDataStepRate = 0;
173
174 polygonLayout[2].SemanticName = "NORMAL";
175 polygonLayout[2].SemanticIndex = 0;
176 polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
177 polygonLayout[2].InputSlot = 0;
178 polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
179 polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
180 polygonLayout[2].InstanceDataStepRate = 0;
181
182 // Get a count of the elements in the layout.
183 numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);
184
185 // Create the vertex input layout.
186 result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(),
187 vertexShaderBuffer->GetBufferSize(), &layout_);
188 if (FAILED(result))
189 {
190 return false;
191 }
192
193 // Release the vertex shader buffer and pixel shader buffer since they are no longer needed.
194 vertexShaderBuffer->Release();
195 vertexShaderBuffer = 0;
196
197 pixelShaderBuffer->Release();
198 pixelShaderBuffer = 0;
199
200 // Setup the description of the dynamic matrix constant buffer that is in the vertex shader.
201 matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
202 matrixBufferDesc.ByteWidth = sizeof(matrix_buffer_type);
203 matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
204 matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
205 matrixBufferDesc.MiscFlags = 0;
206 matrixBufferDesc.StructureByteStride = 0;
207
208 // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class.
209 result = device->CreateBuffer(&matrixBufferDesc, NULL, &matrix_buffer_);
210 if (FAILED(result))
211 {
212 return false;
213 }
214
215 // Create a texture sampler state description.
216 samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
217 samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
218 samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
219 samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
220 samplerDesc.MipLODBias = 0.0f;
221 samplerDesc.MaxAnisotropy = 1;
222 samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
223 samplerDesc.BorderColor[0] = 0;
224 samplerDesc.BorderColor[1] = 0;
225 samplerDesc.BorderColor[2] = 0;
226 samplerDesc.BorderColor[3] = 0;
227 samplerDesc.MinLOD = 0;
228 samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
229
230 // Create the texture sampler state.
231 result = device->CreateSamplerState(&samplerDesc, &sample_state_);
232 if (FAILED(result))
233 {
234 return false;
235 }
236
237 // Setup the description of the light dynamic constant buffer that is in the pixel shader.
238 // Note that ByteWidth always needs to be a multiple of 16 if using D3D11_BIND_CONSTANT_BUFFER or CreateBuffer will fail.
239 lightBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
240 lightBufferDesc.ByteWidth = sizeof(light_buffer_type);
241 lightBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
242 lightBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
243 lightBufferDesc.MiscFlags = 0;
244 lightBufferDesc.StructureByteStride = 0;
245
246 // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class.
247 result = device->CreateBuffer(&lightBufferDesc, NULL, &light_buffer_);
248 if (FAILED(result))
249 {
250 return false;
251 }
252
253 // Setup the description of the clip plane dynamic constant buffer that is in the vertex shader.
254 clipPlaneBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
255 clipPlaneBufferDesc.ByteWidth = sizeof(clip_plane_buffer_type);
256 clipPlaneBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
257 clipPlaneBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
258 clipPlaneBufferDesc.MiscFlags = 0;
259 clipPlaneBufferDesc.StructureByteStride = 0;
260
261 // Create the constant buffer pointer so we can access the vertex shader constant buffer from within this class.
262 result = device->CreateBuffer(&clipPlaneBufferDesc, NULL, &clip_plane_buffer_);
263 if (FAILED(result))
264 {
265 return false;
266 }
267
268 return true;
269}
270
271
272void refraction_shader_class::shutdown_shader()
273{
274 // Release the clip plane constant buffer.
275 if (clip_plane_buffer_)
276 {
277 clip_plane_buffer_->Release();
278 clip_plane_buffer_ = 0;
279 }
280
281 // Release the light constant buffer.
282 if (light_buffer_)
283 {
284 light_buffer_->Release();
285 light_buffer_ = 0;
286 }
287
288 // Release the sampler state.
289 if (sample_state_)
290 {
291 sample_state_->Release();
292 sample_state_ = 0;
293 }
294
295 // Release the matrix constant buffer.
296 if (matrix_buffer_)
297 {
298 matrix_buffer_->Release();
299 matrix_buffer_ = 0;
300 }
301
302 // Release the layout.
303 if (layout_)
304 {
305 layout_->Release();
306 layout_ = 0;
307 }
308
309 // Release the pixel shader.
310 if (pixel_shader_)
311 {
312 pixel_shader_->Release();
313 pixel_shader_ = 0;
314 }
315
316 // Release the vertex shader.
317 if (vertex_shader_)
318 {
319 vertex_shader_->Release();
320 vertex_shader_ = 0;
321 }
322
323 return;
324}
325
326
327void refraction_shader_class::output_shader_error_message(ID3D10Blob* errorMessage, HWND hwnd, WCHAR* shaderFilename)
328{
329 char* compileErrors;
330 unsigned long long bufferSize, i;
331 ofstream fout;
332
333
334 // Get a pointer to the error message text buffer.
335 compileErrors = (char*)(errorMessage->GetBufferPointer());
336
337 // Get the length of the message.
338 bufferSize = errorMessage->GetBufferSize();
339
340 // Open a file to write the error message to.
341 fout.open("shader-error.txt");
342
343 // Write out the error message.
344 for (i = 0; i < bufferSize; i++)
345 {
346 fout << compileErrors[i];
347 }
348
349 // Close the file.
350 fout.close();
351
352 // Release the error message.
353 errorMessage->Release();
354 errorMessage = 0;
355
356 // Pop a message up on the screen to notify the user to check the text file for compile errors.
357 MessageBox(hwnd, L"Error compiling shader. Check shader-error.txt for message.", shaderFilename, MB_OK);
358
359 return;
360}
361
362
363bool refraction_shader_class::set_shader_parameters(ID3D11DeviceContext* deviceContext, XMMATRIX worldMatrix, XMMATRIX viewMatrix, XMMATRIX projectionMatrix,
364 ID3D11ShaderResourceView* texture, XMFLOAT3 lightDirection, XMFLOAT4 ambientColor[], XMFLOAT4 diffuseColor[], XMFLOAT4 lightPosition[], XMFLOAT4 clipPlane)
365{
366 HRESULT result;
367 D3D11_MAPPED_SUBRESOURCE mappedResource;
368 matrix_buffer_type* dataPtr;
369 unsigned int bufferNumber;
370 clip_plane_buffer_type* dataPtr2;
371 light_buffer_type* dataPtr3;
372
373
374 // Transpose the matrices to prepare them for the shader.
375 worldMatrix = XMMatrixTranspose(worldMatrix);
376 viewMatrix = XMMatrixTranspose(viewMatrix);
377 projectionMatrix = XMMatrixTranspose(projectionMatrix);
378
379 // Lock the constant buffer so it can be written to.
380 result = deviceContext->Map(matrix_buffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
381 if (FAILED(result))
382 {
383 return false;
384 }
385
386 // Get a pointer to the data in the constant buffer.
387 dataPtr = (matrix_buffer_type*)mappedResource.pData;
388
389 // Copy the matrices into the constant buffer.
390 dataPtr->world = worldMatrix;
391 dataPtr->view = viewMatrix;
392 dataPtr->projection = projectionMatrix;
393
394 // Unlock the constant buffer.
395 deviceContext->Unmap(matrix_buffer_, 0);
396
397 // Set the position of the constant buffer in the vertex shader.
398 bufferNumber = 0;
399
400 // Finally set the constant buffer in the vertex shader with the updated values.
401 deviceContext->VSSetConstantBuffers(bufferNumber, 1, &matrix_buffer_);
402
403 // Lock the clip plane constant buffer so it can be written to.
404 result = deviceContext->Map(clip_plane_buffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
405 if(FAILED(result))
406 {
407 return false;
408 }
409
410 // Get a pointer to the data in the clip plane constant buffer.
411 dataPtr2 = (clip_plane_buffer_type*)mappedResource.pData;
412
413 // Copy the clip plane into the clip plane constant buffer.
414 dataPtr2->clip_plane = clipPlane;
415
416 // Unlock the buffer.
417 deviceContext->Unmap(clip_plane_buffer_, 0);
418
419 // Set the position of the clip plane constant buffer in the vertex shader.
420 bufferNumber = 1;
421
422 // Now set the clip plane constant buffer in the vertex shader with the updated values.
423 deviceContext->VSSetConstantBuffers(bufferNumber, 1, &clip_plane_buffer_);
424
425 // Set shader texture resource in the pixel shader.
426 deviceContext->PSSetShaderResources(0, 1, &texture);
427
428 // Lock the light constant buffer so it can be written to.
429 result = deviceContext->Map(light_buffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
430 if(FAILED(result))
431 {
432 return false;
433 }
434
435 // Get a pointer to the data in the constant buffer.
436 dataPtr3 = (light_buffer_type*)mappedResource.pData;
437
438 // Copy the lighting variables into the constant buffer.
439 dataPtr3->ambient_color = ambientColor[0];
440 dataPtr3->diffuse_color = diffuseColor[0];
441 dataPtr3->light_position = lightPosition[0];
442 dataPtr3->light_direction = lightDirection;
443
444 // Unlock the constant buffer.
445 deviceContext->Unmap(light_buffer_, 0);
446
447 // Set the position of the light constant buffer in the pixel shader.
448 bufferNumber = 0;
449
450 // Finally set the light constant buffer in the pixel shader with the updated values.
451 deviceContext->PSSetConstantBuffers(bufferNumber, 1, &light_buffer_);
452
453 return true;
454}
455
456
457void refraction_shader_class::render_shader(ID3D11DeviceContext* deviceContext, int indexCount)
458{
459 // Set the vertex input layout.
460 deviceContext->IASetInputLayout(layout_);
461
462 // Set the vertex and pixel shaders that will be used to render the geometry.
463 deviceContext->VSSetShader(vertex_shader_, NULL, 0);
464 deviceContext->PSSetShader(pixel_shader_, NULL, 0);
465
466 // Set the sampler state in the pixel shader.
467 deviceContext->PSSetSamplers(0, 1, &sample_state_);
468
469 // render the geometry.
470 deviceContext->DrawIndexed(indexCount, 0, 0);
471
472 return;
473}