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