forked from vixorien/D3D11Starter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSkybox.cpp
215 lines (188 loc) · 8.28 KB
/
Skybox.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#include "Skybox.h"
#include "Graphics.h"
#include "WICTextureLoader.h"
#include "PathHelpers.h"
using namespace std;
using namespace DirectX;
/// <summary>
/// Creates a Skybox
/// </summary>
/// <param name="_name">Internal name</param>
/// <param name="_mesh">The Mesh to use (usually a cube)</param>
/// <param name="_samplerState">The sampler state to use for rendering</param>
/// <param name="_vertexShader">The vertex shader to use for rendering</param>
/// <param name="_pixelShader">The pixel shader to use for rendering</param>
/// <param name="_pathBase">The starting filepath of the textures to be loaded for the skybox.
/// Files are expected in the format of [_pathBase]_[R, L, U, D, F, or B].png</param>
Skybox::Skybox(
const char* _name,
shared_ptr<Mesh> _mesh,
Microsoft::WRL::ComPtr<ID3D11SamplerState> _samplerState,
shared_ptr<SimpleVertexShader> _vertexShader,
shared_ptr<SimplePixelShader> _pixelShader,
std::wstring _pathBase
)
{
// Initialize member variables from constructor parameters
name = _name;
mesh = _mesh;
samplerState = _samplerState;
// Construct file paths from base
wstring pathR = _pathBase + L"_R.png";
wstring pathL = _pathBase + L"_L.png";
wstring pathU = _pathBase + L"_U.png";
wstring pathD = _pathBase + L"_D.png";
wstring pathF = _pathBase + L"_F.png";
wstring pathB = _pathBase + L"_B.png";
srv = CreateCubemap(
FixPath(pathR).c_str(),
FixPath(pathL).c_str(),
FixPath(pathU).c_str(),
FixPath(pathD).c_str(),
FixPath(pathF).c_str(),
FixPath(pathB).c_str()
);
vertexShader = _vertexShader;
pixelShader = _pixelShader;
// Create Rasterizer and Depth Stencil states
D3D11_RASTERIZER_DESC rasterizerDesc = {};
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.CullMode = D3D11_CULL_FRONT;
rasterizerDesc.DepthClipEnable = true;
Graphics::Device->CreateRasterizerState(&rasterizerDesc, rasterizerState.GetAddressOf());
D3D11_DEPTH_STENCIL_DESC depthDesc = {};
depthDesc.DepthEnable = true;
depthDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
Graphics::Device->CreateDepthStencilState(&depthDesc, depthState.GetAddressOf());
}
/// <summary>
/// Draws the skybox to the screen
/// </summary>
/// <param name="camera">The camera to draw from</param>
void Skybox::Draw(shared_ptr<Camera> camera)
{
// Set rasterizer and depth stencil states
Graphics::Context->RSSetState(rasterizerState.Get());
Graphics::Context->OMSetDepthStencilState(depthState.Get(), 0);
// Set vertex and pixel shaders and their associated data
vertexShader->SetShader();
vertexShader->SetMatrix4x4("tfView", camera->GetViewMatrix());
vertexShader->SetMatrix4x4("tfProjection", camera->GetProjectionMatrix());
pixelShader->SetShader();
pixelShader->SetSamplerState("BasicSampler", samplerState);
pixelShader->SetShaderResourceView("MapCube", srv);
vertexShader->CopyAllBufferData();
// Draw mesh
mesh->Draw();
// Reset rasterizer and depth stencil states
Graphics::Context->RSSetState(0);
Graphics::Context->OMSetDepthStencilState(0, 0);
}
/// <summary>
/// Gets the Skybox's Shader Resource View
/// </summary>
/// <returns>The Skybox texture's SRV</returns>
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> Skybox::GetSRV()
{
return srv;
}
/// <summary>
/// Gets the Skybox's name
/// </summary>
/// <returns>The internal name of the Skybox</returns>
const char* Skybox::GetName()
{
return name;
}
// --------------------------------------------------------
// Author: Chris Cascioli
// Purpose: Creates a cube map on the GPU from 6 individual textures
//
// - You are allowed to directly copy/paste this into your code base
// for assignments, given that you clearly cite that this is not
// code of your own design.
//
// - Note: This code assumes you’re putting the function in Sky.cpp,
// you’ve included WICTextureLoader.h and you have an ID3D11Device
// ComPtr called “device”. Make any adjustments necessary for
// your own implementation.
// --------------------------------------------------------
// --------------------------------------------------------
// Loads six individual textures (the six faces of a cube map), then
// creates a blank cube map and copies each of the six textures to
// another face. Afterwards, creates a shader resource view for
// the cube map and cleans up all of the temporary resources.
// --------------------------------------------------------
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> Skybox::CreateCubemap(
const wchar_t* right,
const wchar_t* left,
const wchar_t* up,
const wchar_t* down,
const wchar_t* front,
const wchar_t* back)
{
// Load the 6 textures into an array.
// - We need references to the TEXTURES, not SHADER RESOURCE VIEWS!
// - Explicitly NOT generating mipmaps, as we don't need them for the sky!
// - Order matters here! +X, -X, +Y, -Y, +Z, -Z
Microsoft::WRL::ComPtr<ID3D11Texture2D> textures[6] = {};
CreateWICTextureFromFile(Graphics::Device.Get(), right, (ID3D11Resource**)textures[0].GetAddressOf(), 0);
CreateWICTextureFromFile(Graphics::Device.Get(), left, (ID3D11Resource**)textures[1].GetAddressOf(), 0);
CreateWICTextureFromFile(Graphics::Device.Get(), up, (ID3D11Resource**)textures[2].GetAddressOf(), 0);
CreateWICTextureFromFile(Graphics::Device.Get(), down, (ID3D11Resource**)textures[3].GetAddressOf(), 0);
CreateWICTextureFromFile(Graphics::Device.Get(), front, (ID3D11Resource**)textures[4].GetAddressOf(), 0);
CreateWICTextureFromFile(Graphics::Device.Get(), back, (ID3D11Resource**)textures[5].GetAddressOf(), 0);
// We'll assume all of the textures are the same color format and resolution,
// so get the description of the first texture
D3D11_TEXTURE2D_DESC faceDesc = {};
textures[0]->GetDesc(&faceDesc);
// Describe the resource for the cube map, which is simply
// a "texture 2d array" with the TEXTURECUBE flag set.
// This is a special GPU resource format, NOT just a
// C++ array of textures!!!
D3D11_TEXTURE2D_DESC cubeDesc = {};
cubeDesc.ArraySize = 6; // Cube map!
cubeDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; // We'll be using as a texture in a shader
cubeDesc.CPUAccessFlags = 0; // No read back
cubeDesc.Format = faceDesc.Format; // Match the loaded texture's color format
cubeDesc.Width = faceDesc.Width; // Match the size
cubeDesc.Height = faceDesc.Height; // Match the size
cubeDesc.MipLevels = 1; // Only need 1
cubeDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; // This should be treated as a CUBE, not 6 separate textures
cubeDesc.Usage = D3D11_USAGE_DEFAULT; // Standard usage
cubeDesc.SampleDesc.Count = 1;
cubeDesc.SampleDesc.Quality = 0;
// Create the final texture resource to hold the cube map
Microsoft::WRL::ComPtr<ID3D11Texture2D> cubeMapTexture;
Graphics::Device->CreateTexture2D(&cubeDesc, 0, cubeMapTexture.GetAddressOf());
// Loop through the individual face textures and copy them,
// one at a time, to the cube map texure
for (int i = 0; i < 6; i++)
{
// Calculate the subresource position to copy into
unsigned int subresource = D3D11CalcSubresource(
0, // Which mip (zero, since there's only one)
i, // Which array element?
1); // How many mip levels are in the texture?
// Copy from one resource (texture) to another
Graphics::Context->CopySubresourceRegion(
cubeMapTexture.Get(), // Destination resource
subresource, // Dest subresource index (one of the array elements)
0, 0, 0, // XYZ location of copy
textures[i].Get(), // Source resource
0, // Source subresource index (we're assuming there's only one)
0); // Source subresource "box" of data to copy (zero means the whole thing)
}
// At this point, all of the faces have been copied into the
// cube map texture, so we can describe a shader resource view for it
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Format = cubeDesc.Format; // Same format as texture
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; // Treat this as a cube!
srvDesc.TextureCube.MipLevels = 1; // Only need access to 1 mip
srvDesc.TextureCube.MostDetailedMip = 0; // Index of the first mip we want to see
// Make the SRV
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> cubeSRV;
Graphics::Device->CreateShaderResourceView(cubeMapTexture.Get(), &srvDesc, cubeSRV.GetAddressOf());
// Send back the SRV, which is what we need for our shaders
return cubeSRV;
}