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