diff --git a/DXCore.h b/DXCore.h index 534cc1c..4880a06 100644 --- a/DXCore.h +++ b/DXCore.h @@ -44,6 +44,13 @@ public: virtual void Update(float deltaTime, float totalTime) = 0; virtual void Draw(float deltaTime, float totalTime) = 0; + // Helpers for determining the actual path to the executable + static std::string GetExePath(); + static std::wstring GetExePath_Wide(); + + static std::string GetFullPathTo(std::string relativeFilePath); + static std::wstring GetFullPathTo_Wide(std::wstring relativeFilePath); + protected: HINSTANCE hInstance; // The handle to the application HWND hWnd; // The handle to the window itself @@ -70,13 +77,6 @@ protected: // Helper function for allocating a console window void CreateConsoleWindow(int bufferLines, int bufferColumns, int windowLines, int windowColumns); - // Helpers for determining the actual path to the executable - std::string GetExePath(); - std::wstring GetExePath_Wide(); - - std::string GetFullPathTo(std::string relativeFilePath); - std::wstring GetFullPathTo_Wide(std::wstring relativeFilePath); - private: // Timing related data diff --git a/Game.cpp b/Game.cpp index 3cfb69f..1381f94 100644 --- a/Game.cpp +++ b/Game.cpp @@ -48,7 +48,6 @@ Game::~Game() // we don't need to explicitly clean up those DirectX objects // - If we weren't using smart pointers, we'd need // to call Release() on each DirectX object created in Game - } // -------------------------------------------------------- @@ -57,10 +56,7 @@ Game::~Game() // -------------------------------------------------------- void Game::Init() { - // Helper methods for loading shaders, creating some basic - // geometry to draw and some simple camera matrices. - // - You'll be expanding and/or replacing these later - LoadShaders(); + LoadShadersAndMaterials(); LoadTextures(); LoadLighting(); CreateBasicGeometry(); @@ -72,14 +68,9 @@ void Game::Init() } // -------------------------------------------------------- -// Loads shaders from compiled shader object (.cso) files -// and also created the Input Layout that describes our -// vertex data to the rendering pipeline. -// - Input Layout creation is done here because it must -// be verified against vertex shader byte code -// - We'll have that byte code already loaded below +// Loads shaders from compiled shader object (.cso) files and pushes them to materials // -------------------------------------------------------- -void Game::LoadShaders() +void Game::LoadShadersAndMaterials() { vertexShader = std::make_shared<SimpleVertexShader>(device, context, GetFullPathTo_Wide(L"VertexShader.cso").c_str()); pixelShader = std::make_shared<SimplePixelShader>(device, context, GetFullPathTo_Wide(L"SimplePixelShader.cso").c_str()); @@ -92,6 +83,9 @@ void Game::LoadShaders() }; } +// -------------------------------------------------------- +// Loads textures and pushes them to the loaded materials +// -------------------------------------------------------- void Game::LoadTextures() { Microsoft::WRL::ComPtr<ID3D11SamplerState> sampler; @@ -105,76 +99,31 @@ void Game::LoadTextures() sampDesc.MaxLOD = D3D11_FLOAT32_MAX; device->CreateSamplerState(&sampDesc, sampler.GetAddressOf()); - Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> - deepFloorEmissive, - deepFloorSpecular, - deepFloorAlbedo, - floorEmissive, - floorSpecular, - floorAlbedo; - - // taking the preprocessor macro from the demo because I don't like typing - #define GetTex(pathToTexture, shaderResourceView) CreateWICTextureFromFile(device.Get(), context.Get(), GetFullPathTo_Wide(pathToTexture).c_str(), 0, shaderResourceView.GetAddressOf()); - - GetTex(L"Assets/Textures/HQGame/structure-endgame-deepfloor_emissive.png", deepFloorEmissive); - GetTex(L"Assets/Textures/HQGame/structure-endgame-deepfloor_specular.png", deepFloorSpecular); - GetTex(L"Assets/Textures/HQGame/structure-endgame-deepfloor_albedo.png", deepFloorAlbedo); - GetTex(L"Assets/Textures/HQGame/structure-endgame-floor_emissive.png", floorEmissive); - GetTex(L"Assets/Textures/HQGame/structure-endgame-floor_specular.png", floorSpecular); - GetTex(L"Assets/Textures/HQGame/structure-endgame-floor_albedo.png", floorAlbedo); - materials[0]->PushSampler("BasicSampler", sampler); - materials[0]->PushTexture("Albedo", deepFloorAlbedo); - materials[0]->PushTexture("Specular", deepFloorSpecular); - materials[0]->PushTexture("Emissive", deepFloorEmissive); + materials[0]->LoadTexture(L"Assets/Textures/HQGame/structure-endgame-deepfloor_albedo.png", TEXTYPE_ALBEDO, device.Get(), context.Get()); + materials[0]->LoadTexture(L"Assets/Textures/HQGame/structure-endgame-deepfloor_specular.png", TEXTYPE_SPECULAR, device.Get(), context.Get()); + materials[0]->LoadTexture(L"Assets/Textures/HQGame/structure-endgame-deepfloor_emissive.png", TEXTYPE_EMISSIVE, device.Get(), context.Get()); + materials[1]->PushSampler("BasicSampler", sampler); - materials[1]->PushTexture("Albedo", floorAlbedo); - materials[1]->PushTexture("Specular", floorSpecular); - materials[1]->PushTexture("Emissive", floorEmissive); + materials[1]->LoadTexture(L"Assets/Textures/HQGame/structure-endgame-floor_albedo.png", TEXTYPE_ALBEDO, device.Get(), context.Get()); + materials[1]->LoadTexture(L"Assets/Textures/HQGame/structure-endgame-floor_specular.png", TEXTYPE_SPECULAR, device.Get(), context.Get()); + materials[1]->LoadTexture(L"Assets/Textures/HQGame/structure-endgame-floor_emissive.png", TEXTYPE_EMISSIVE, device.Get(), context.Get()); } +// -------------------------------------------------------- +// Instantiates all the lighting in the scene +// -------------------------------------------------------- void Game::LoadLighting() { ambient = XMFLOAT3(0.1f, 0.1f, 0.15f); - Light directionalLight0 = {}; - directionalLight0.Type = LIGHT_TYPE_DIRECTIONAL; - directionalLight0.Direction = XMFLOAT3(1, 0.5f, 0.5f); - directionalLight0.Color = XMFLOAT3(1, 1, 1); - directionalLight0.Intensity = 0.5f; - - Light directionalLight1 = {}; - directionalLight1.Type = LIGHT_TYPE_DIRECTIONAL; - directionalLight1.Direction = XMFLOAT3(-0.25f, -1, 0.75f); - directionalLight1.Color = XMFLOAT3(1, 1, 1); - directionalLight1.Intensity = 0.5f; - - Light directionalLight2 = {}; - directionalLight2.Type = LIGHT_TYPE_DIRECTIONAL; - directionalLight2.Direction = XMFLOAT3(-1, 1, -0.5f); - directionalLight2.Color = XMFLOAT3(1, 1, 1); - directionalLight2.Intensity = 0.5f; - - Light pointLight0 = {}; - pointLight0.Type = LIGHT_TYPE_POINT; - pointLight0.Position = XMFLOAT3(-1.5f, 0, 0); - pointLight0.Color = XMFLOAT3(1, 1, 1); - pointLight0.Intensity = 0.5f; - pointLight0.Range = 10; - - Light pointLight1 = {}; - pointLight1.Type = LIGHT_TYPE_POINT; - pointLight1.Position = XMFLOAT3(1.5f, 0, 0); - pointLight1.Color = XMFLOAT3(1, 1, 1); - pointLight1.Intensity = 0.25f; - pointLight1.Range = 10; - lights = { - directionalLight0, - directionalLight1, - directionalLight2, - pointLight0, - pointLight1, + Light::Directional(XMFLOAT3(1, 0.5f, 0.5f), XMFLOAT3(1, 1, 1), 0.5f), + Light::Directional(XMFLOAT3(-0.25f, -1, 0.75f), XMFLOAT3(1, 1, 1), 0.5f), + Light::Directional(XMFLOAT3(-1, 1, -0.5f), XMFLOAT3(1, 1, 1), 0.5f), + Light::Point(XMFLOAT3(-1.5f, 0, 0), XMFLOAT3(1, 1, 1), 0.5f, 10), + Light::Point(XMFLOAT3(1.5f, 0, 0), XMFLOAT3(1, 1, 1), 0.25f, 10), + Light::Point(XMFLOAT3(0, 2, 0), XMFLOAT3(1, 0, 0), 0.25f, 10), }; } @@ -211,7 +160,7 @@ void Game::CreateBasicGeometry() std::make_shared<Entity>(materials[0], shapes[0]), std::make_shared<Entity>(materials[0], shapes[1]), std::make_shared<Entity>(materials[0], shapes[2]), - std::make_shared<Entity>(materials[1], shapes[3]), + std::make_shared<Entity>(materials[0], shapes[3]), std::make_shared<Entity>(materials[1], shapes[4]), std::make_shared<Entity>(materials[1], shapes[5]), std::make_shared<Entity>(materials[1], shapes[6]), @@ -220,6 +169,7 @@ void Game::CreateBasicGeometry() for (int i = 0; i < entities.size(); ++i) { entities[i]->GetTransform()->SetPosition((-(int)(entities.size() / 2) + i) * 5, 0, 0); + entities[i]->GetMaterial()->SetEmitAmount((entities.size() - i) * 0.25f); } } @@ -242,7 +192,6 @@ void Game::OnResize() // -------------------------------------------------------- void Game::Update(float deltaTime, float totalTime) { - // Example input checking: Quit if the escape key is pressed if (Input::GetInstance().KeyDown(VK_ESCAPE)) Quit(); @@ -251,10 +200,6 @@ void Game::Update(float deltaTime, float totalTime) for (int i = 0; i < entities.size(); ++i) { entities[i]->GetTransform()->SetRotation(sin(totalTime / 720) * 360, 0, 0); - entities[i]->GetMaterial()->SetRoughness(sin(totalTime) * 0.5f + 0.49f); - entities[i]->GetMaterial()->SetUVOffset(DirectX::XMFLOAT2(cos(totalTime * 4) * 0.5f + 0.49f, cos(totalTime * 4) * 0.5f + 0.49f)); - entities[i]->GetMaterial()->SetUVScale(DirectX::XMFLOAT2(sin(totalTime) * 0.5f + 0.49f, sin(totalTime) * 0.5f + 0.49f)); - entities[i]->GetMaterial()->SetEmitAmount(cos(totalTime) * 0.5f + 0.49f); } } diff --git a/Game.h b/Game.h index b8be745..f62f3f3 100644 --- a/Game.h +++ b/Game.h @@ -15,33 +15,23 @@ class Game : public DXCore { - public: Game(HINSTANCE hInstance); ~Game(); - // Overridden setup and game loop methods, which - // will be called automatically void Init(); void OnResize(); void Update(float deltaTime, float totalTime); void Draw(float deltaTime, float totalTime); private: - // Should we use vsync to limit the frame rate? bool vsync; - // Initialization helper methods - feel free to customize, combine, etc. - void LoadShaders(); + void LoadShadersAndMaterials(); void LoadTextures(); void LoadLighting(); void CreateBasicGeometry(); - - // Note the usage of ComPtr below - // - This is a smart pointer for objects that abide by the - // Component Object Model, which DirectX objects do - // - More info here: https://github.com/Microsoft/DirectXTK/wiki/ComPtr // Shaders and shader-related constructs std::shared_ptr<SimplePixelShader> pixelShader; diff --git a/Lights.h b/Lights.h index 546f6f6..8762f66 100644 --- a/Lights.h +++ b/Lights.h @@ -2,9 +2,9 @@ #include <DirectXMath.h> -#define LIGHT_TYPE_DIRECTIONAL 0 -#define LIGHT_TYPE_POINT 1 -#define LIGHT_TYPE_SPOT 2 +constexpr auto LIGHT_TYPE_DIRECTIONAL = 0; +constexpr auto LIGHT_TYPE_POINT = 1; +constexpr auto LIGHT_TYPE_SPOT = 2; struct Light { @@ -16,4 +16,25 @@ struct Light DirectX::XMFLOAT3 Color; float SpotFalloff; DirectX::XMFLOAT3 Padding; + + static Light Directional(DirectX::XMFLOAT3 _direction, DirectX::XMFLOAT3 _color, float _intensity) + { + Light light = {}; + light.Type = LIGHT_TYPE_DIRECTIONAL; + light.Direction = _direction; + light.Color = _color; + light.Intensity = _intensity; + return light; + }; + + static Light Point(DirectX::XMFLOAT3 _position, DirectX::XMFLOAT3 _color, float _intensity, float _range) + { + Light light = {}; + light.Type = LIGHT_TYPE_POINT; + light.Position = _position; + light.Color = _color; + light.Intensity = _intensity; + light.Range = _range; + return light; + }; }; diff --git a/Material.cpp b/Material.cpp index 25a2bfd..dc99ff6 100644 --- a/Material.cpp +++ b/Material.cpp @@ -12,6 +12,7 @@ Material::Material( pixelShader = _pixelShader; uvOffset = DirectX::XMFLOAT2(0, 0); uvScale = DirectX::XMFLOAT2(1, 1); + emitAmount = 0; } Material::~Material() @@ -34,6 +35,7 @@ void Material::Activate(Transform* _transform, std::shared_ptr<Camera> _camera, pixelShader->SetFloat3("ambient", _ambient); pixelShader->SetFloat("emitAmount", GetEmitAmount()); pixelShader->SetFloat3("tint", GetTint()); + pixelShader->SetFloat("lightCount", (int)_lights.size()); pixelShader->SetData("lights", &_lights[0], sizeof(Light) * (int)_lights.size()); pixelShader->CopyAllBufferData(); pixelShader->SetShader(); @@ -129,6 +131,13 @@ void Material::SetPixelShader(std::shared_ptr<SimplePixelShader> _pixelShader) pixelShader = _pixelShader; } +void Material::LoadTexture(const wchar_t* _path, const char* _type, ID3D11Device* _device, ID3D11DeviceContext* _context) +{ + Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> shaderResourceView; + DirectX::CreateWICTextureFromFile(_device, _context, DXCore::GetFullPathTo_Wide(_path).c_str(), 0, shaderResourceView.GetAddressOf()); + PushTexture(_type, shaderResourceView); +} + void Material::PushSampler(std::string _name, Microsoft::WRL::ComPtr<ID3D11SamplerState> _sampler) { samplers.insert({ _name, _sampler }); diff --git a/Material.h b/Material.h index c3df313..cdbd90b 100644 --- a/Material.h +++ b/Material.h @@ -2,10 +2,17 @@ #include <DirectXMath.h> #include <memory> +#include "DXCore.h" #include "SimpleShader.h" #include "Transform.h" #include "Camera.h" #include "Lights.h" +#include "WICTextureLoader.h" + +constexpr auto TEXTYPE_ALBEDO = "Albedo"; +constexpr auto TEXTYPE_NORMAL = "Normal"; +constexpr auto TEXTYPE_EMISSIVE = "Emissive"; +constexpr auto TEXTYPE_SPECULAR = "Specular"; class Material { @@ -39,6 +46,7 @@ public: void SetVertexShader(std::shared_ptr<SimpleVertexShader> _vertexShader); void SetPixelShader(std::shared_ptr<SimplePixelShader> _pixelShader); + void LoadTexture(const wchar_t* _path, const char* _type, ID3D11Device* _device, ID3D11DeviceContext* _context); void PushSampler(std::string _name, Microsoft::WRL::ComPtr<ID3D11SamplerState> _sampler); void PushTexture(std::string _name, Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> _texture); diff --git a/SimplePixelShader.hlsl b/SimplePixelShader.hlsl index 7fa6b0b..a7c90d2 100644 --- a/SimplePixelShader.hlsl +++ b/SimplePixelShader.hlsl @@ -2,19 +2,23 @@ #include "Helpers.hlsli" #include "Lights.hlsli" -// temporary -#define LIGHT_COUNT 5 +#define MAX_LIGHTS 128 cbuffer ExternalData : register(b0) { float3 cameraPosition; float roughness; + float2 offset; float2 scale; + float3 ambient; float emitAmount; + float3 tint; - Light lights[LIGHT_COUNT]; + float lightCount; + + Light lights[MAX_LIGHTS]; } Texture2D Albedo : register(t0); @@ -70,7 +74,7 @@ float4 main(VertexToPixel input) : SV_TARGET float3 light = ambient * surface; // loop through lights - for (int i = 0; i < LIGHT_COUNT; i++) + for (int i = 0; i < lightCount; i++) { switch (lights[i].Type) {