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