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