From bedfe0d5f599391b789c9bd8652e331ed9261af8 Mon Sep 17 00:00:00 2001 From: Lightling Date: Sun, 3 Apr 2022 18:01:59 -0400 Subject: [PATCH] define Sky.cpp / Sky.h and Game::CreateCubemap --- Game.cpp | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- Game.h | 18 +++++++-- Sky.cpp | 43 +++++++++++++++++++++ Sky.h | 32 ++++++++++++++++ 4 files changed, 199 insertions(+), 5 deletions(-) create mode 100644 Sky.cpp create mode 100644 Sky.h diff --git a/Game.cpp b/Game.cpp index b033a2c..5a225b6 100644 --- a/Game.cpp +++ b/Game.cpp @@ -249,4 +249,113 @@ void Game::Draw(float deltaTime, float totalTime) // Due to the usage of a more sophisticated swap chain, // the render target must be re-bound after every call to Present() context->OMSetRenderTargets(1, backBufferRTV.GetAddressOf(), depthStencilView.Get()); -} \ No newline at end of file +} + +// -------------------------------------------------------- +// 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 Game::CreateCubemap( + Microsoft::WRL::ComPtr device, + Microsoft::WRL::ComPtr context, + const wchar_t* right, + const wchar_t* left, + const wchar_t* up, + const wchar_t* down, + const wchar_t* front, + const wchar_t* back) +{ + +// -------------------------------------------------------- +// 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 Game.cpp, +// you’ve included WICTextureLoader.h and you have an ID3D11Device +// ComPtr called “device”. Make any adjustments necessary for +// your own implementation. +// -------------------------------------------------------- + + // Load the 6 textures into an array. + // - We need references to the TEXTURES, not the SHADER RESOURCE VIEWS! + // - Specifically NOT generating mipmaps, as we usually don't need them for the sky! + // - Order matters here! +X, -X, +Y, -Y, +Z, -Z + ID3D11Texture2D* textures[6] = {}; + CreateWICTextureFromFile(device.Get(), right, (ID3D11Resource**)&textures[0], 0); + CreateWICTextureFromFile(device.Get(), left, (ID3D11Resource**)&textures[1], 0); + CreateWICTextureFromFile(device.Get(), up, (ID3D11Resource**)&textures[2], 0); + CreateWICTextureFromFile(device.Get(), down, (ID3D11Resource**)&textures[3], 0); + CreateWICTextureFromFile(device.Get(), front, (ID3D11Resource**)&textures[4], 0); + CreateWICTextureFromFile(device.Get(), back, (ID3D11Resource**)&textures[5], 0); + + // We'll assume all of the textures are the same color format and resolution, + // so get the description of the first shader resource view + D3D11_TEXTURE2D_DESC faceDesc = {}; + textures[0]->GetDesc(&faceDesc); + + // Describe the resource for the cube map, which is simply + // a "texture 2d array". 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; // A CUBE MAP, not 6 separate textures + cubeDesc.Usage = D3D11_USAGE_DEFAULT; // Standard usage + cubeDesc.SampleDesc.Count = 1; + cubeDesc.SampleDesc.Quality = 0; + + // Create the actual texture resource + ID3D11Texture2D* cubeMapTexture = 0; + device->CreateTexture2D(&cubeDesc, 0, &cubeMapTexture); + + // 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 + context->CopySubresourceRegion( + cubeMapTexture, // Destination resource + subresource, // Dest subresource index (one of the array elements) + 0, 0, 0, // XYZ location of copy + textures[i], // 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 cubeSRV; + device->CreateShaderResourceView(cubeMapTexture, &srvDesc, cubeSRV.GetAddressOf()); + + // Now that we're done, clean up the stuff we don't need anymore + cubeMapTexture->Release(); // Done with this particular reference (the SRV has another) + for (int i = 0; i < 6; i++) + textures[i]->Release(); + + // Send back the SRV, which is what we need for our shaders + return cubeSRV; +} diff --git a/Game.h b/Game.h index f62f3f3..712d23c 100644 --- a/Game.h +++ b/Game.h @@ -19,10 +19,20 @@ public: Game(HINSTANCE hInstance); ~Game(); - void Init(); - void OnResize(); - void Update(float deltaTime, float totalTime); - void Draw(float deltaTime, float totalTime); + void Init(); + void OnResize(); + void Update(float deltaTime, float totalTime); + void Draw(float deltaTime, float totalTime); + + static Microsoft::WRL::ComPtr CreateCubemap( + Microsoft::WRL::ComPtr _device, + Microsoft::WRL::ComPtr _context, + const wchar_t* _right, + const wchar_t* _left, + const wchar_t* _up, + const wchar_t* _down, + const wchar_t* _front, + const wchar_t* _back); private: // Should we use vsync to limit the frame rate? diff --git a/Sky.cpp b/Sky.cpp new file mode 100644 index 0000000..b61a481 --- /dev/null +++ b/Sky.cpp @@ -0,0 +1,43 @@ +#include "Sky.h" + +Sky::Sky(std::shared_ptr _mesh, Microsoft::WRL::ComPtr _cubemap, Microsoft::WRL::ComPtr _sampler, Microsoft::WRL::ComPtr _device) +{ + mesh = _mesh; + cubemap = _cubemap; + sampler = _sampler; + + D3D11_RASTERIZER_DESC rDesc = {}; + rDesc.FillMode = D3D11_FILL_SOLID; + rDesc.CullMode = D3D11_CULL_FRONT; + _device->CreateRasterizerState(&rDesc, rasterizerState.GetAddressOf()); + + D3D11_DEPTH_STENCIL_DESC dDesc = {}; + dDesc.DepthEnable = true; + dDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; + _device->CreateDepthStencilState(&dDesc, depthState.GetAddressOf()); +} + +Sky::~Sky() +{ +} + +void Sky::Draw(Microsoft::WRL::ComPtr _context, Camera* _camera) +{ + _context->RSSetState(rasterizerState.Get()); + _context->OMSetDepthStencilState(depthState.Get(), 0); + + vertexShader->SetMatrix4x4("view", _camera->GetViewMatrix()); + vertexShader->SetMatrix4x4("projection", _camera->GetProjectionMatrix()); + vertexShader->CopyAllBufferData(); + vertexShader->SetShader(); + + pixelShader->SetShaderResourceView("SkyTexture", cubemap.Get()); + pixelShader->SetSamplerState("Sampler", sampler.Get()); + pixelShader->CopyAllBufferData(); + pixelShader->SetShader(); + + mesh->Draw(); + + _context->RSSetState(0); + _context->OMSetDepthStencilState(0, 0); +} diff --git a/Sky.h b/Sky.h new file mode 100644 index 0000000..915c210 --- /dev/null +++ b/Sky.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include +#include "Mesh.h" +#include "SimpleShader.h" +#include "Camera.h" + +class Sky +{ +public: + Sky( + std::shared_ptr _mesh, + Microsoft::WRL::ComPtr _cubemap, + Microsoft::WRL::ComPtr _sampler, + Microsoft::WRL::ComPtr _device); + ~Sky(); + + void Draw( + Microsoft::WRL::ComPtr _context, + Camera* _camera); + +private: + Microsoft::WRL::ComPtr sampler; + Microsoft::WRL::ComPtr depthState; + Microsoft::WRL::ComPtr rasterizerState; + Microsoft::WRL::ComPtr cubemap; + std::shared_ptr mesh; + std::shared_ptr vertexShader; + std::shared_ptr pixelShader; +};