diff --git a/project/CMakeLists.txt b/project/CMakeLists.txt index bc0eb1c..141fa58 100644 --- a/project/CMakeLists.txt +++ b/project/CMakeLists.txt @@ -14,6 +14,9 @@ set(SOURCES "src/Texture.cpp" "src/GamePadController.cpp" "src/Utils.cpp" + "src/BaseEffect.cpp" + "src/FireEffect.cpp" + "src/Material.cpp" ) # Create the executable diff --git a/project/resources/Fire.fx b/project/resources/Fire.fx new file mode 100644 index 0000000..4e8df86 --- /dev/null +++ b/project/resources/Fire.fx @@ -0,0 +1,95 @@ +float4x4 gWorldViewProj : WorldViewProjection; +float4x4 gWorldMatrix : WorldMatrix; + +texture2D gDiffuseMap : DiffuseMap; + +//Input output +struct VS_INPUT { + float3 Position : POSITION; + float2 TexCoord : TEXCOORD; + float3 Normal : NORMAL; + float3 Tangent : TANGENT; +}; + + + +struct VS_OUTPUT { + float4 Position : SV_POSITION; + float4 WorldPosition : WORLDPOSITION; + float2 TexCoord : TEXCOORD; + float3 Normal : NORMAL; + float3 Tangent : TANGENT; +}; + + +//---------------------- +// Rasterizer state +//---------------------- +RasterizerState gRasterizerState +{ + CullMode = none; + FrontCounterClockwise = false; //default +}; + +//---------------------- +// Blend state +//---------------------- +BlendState gBlendState +{ + BlendEnable[0] = true; + SrcBlend = SRC_ALPHA; + DestBlend = INV_SRC_ALPHA; + BlendOp = ADD; + SrcBlendAlpha = ZERO; + DestBlendAlpha = ZERO; + BlendOpAlpha = ADD; + RenderTargetWriteMask[0] = 0x0F; +}; + +//---------------------- +// SamplerState +//---------------------- +SamplerState samPoint +{ + Filter = MIN_MAG_MIP_POINT; + Addressu = Wrap; //or Mirror, Clamp, Border + AddressV = Wrap; //or Mirror, Clamp, Border +}; + +DepthStencilState gDepthStencilState +{ + DepthEnable = true; + DepthWriteMask = ZERO; + DepthFunc = LESS; + StencilEnable = false; +}; + + +//Vertex shader +VS_OUTPUT VS(VS_INPUT input){ + VS_OUTPUT output = (VS_OUTPUT)0; + + output.Position = mul(float4(input.Position, 1.f), gWorldViewProj); + output.WorldPosition = mul(float4(input.Position, 1.f), gWorldMatrix); + output.TexCoord = input.TexCoord; + output.Normal = mul(input.Normal, (float3x3) gWorldMatrix); + output.Tangent = mul(input.Tangent, (float3x3) gWorldMatrix); + + return output; +} + +float4 PS(VS_OUTPUT input) : SV_TARGET{ + return gDiffuseMap.Sample(samPoint, input.TexCoord); +} + + +technique11 DefaultTechnique{ + pass P0 { + SetRasterizerState(gRasterizerState); + SetDepthStencilState(gDepthStencilState, 0); + SetBlendState(gBlendState, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF); + SetVertexShader( CompileShader( vs_5_0, VS() ) ); + SetGeometryShader( NULL ); + SetPixelShader( CompileShader( ps_5_0, PS() ) ); + } +} diff --git a/project/resources/PosCol3D.fx b/project/resources/PosCol3D.fx index ea46b71..b3f0aa9 100644 --- a/project/resources/PosCol3D.fx +++ b/project/resources/PosCol3D.fx @@ -1,40 +1,49 @@ +SamplerState gSampleState : SampleState; + float4x4 gWorldViewProj : WorldViewProjection; +float4x4 gWorldMatrix : WorldMatrix; + texture2D gDiffuseMap : DiffuseMap; +texture2D gNormalMap : Normal; +texture2D gSpecularMap : Specular; +texture2D gGlossMap : Gloss; + +float3 gLightDirection : LightDirection; +float3 gLightColor : LightColor; +float3 gCameraPosition : CameraPosition; +bool gUseNormal : UseNormal; + + +static const float3 gAmbient = float3(.03f, .03f, .03f); +static const float gLightIntensity = 7.f; +static const float PI = 3.14159f; +static const float gSpecularReflectance = 1.f; +static const float gShininess = 25.f; + //Input output -struct VS_INPUT{ +struct VS_INPUT { float3 Position : POSITION; - float3 Color: COLOR; - float2 TexCoord: TEXCOORD; + float2 TexCoord : TEXCOORD; + float3 Normal : NORMAL; + float3 Tangent : TANGENT; }; -struct VS_OUTPUT{ +struct VS_OUTPUT { float4 Position : SV_POSITION; - float3 Color: COLOR; - float2 TexCoord: TEXCOORD; + float4 WorldPosition : WORLDPOSITION; + float2 TexCoord : TEXCOORD; + float3 Normal : NORMAL; + float3 Tangent : TANGENT; }; + //---------------------- -// SamplerState +// Rasterizer state //---------------------- -SamplerState samPoint +RasterizerState gRasterizerState { - Filter = MIN_MAG_MIP_POINT; - Addressu = Wrap; //or Mirror, Clamp, Border - AddressV = Wrap; //or Mirror, Clamp, Border -}; - -SamplerState samLinear -{ - Filter = MIN_MAG_MIP_LINEAR; - Addressu = Wrap; //or Mirror, Clamp, Border - AddressV = Wrap; //or Mirror, Clamp, Border -}; - -SamplerState samAnisotropic -{ - Filter = ANISOTROPIC; - Addressu = Wrap; //or Mirror, Clamp, Border - AddressV = Wrap; //or Mirror, Clamp, Border + CullMode = none; + FrontCounterClockwise = false; //default }; @@ -43,44 +52,88 @@ VS_OUTPUT VS(VS_INPUT input){ VS_OUTPUT output = (VS_OUTPUT)0; output.Position = mul(float4(input.Position, 1.f), gWorldViewProj); - output.Color = input.Color; + output.WorldPosition = mul(float4(input.Position, 1.f), gWorldMatrix); output.TexCoord = input.TexCoord; + output.Normal = mul(input.Normal, (float3x3) gWorldMatrix); + output.Tangent = mul(input.Tangent, (float3x3) gWorldMatrix); return output; } -float4 PS_point(VS_OUTPUT input) : SV_TARGET{ - return gDiffuseMap.Sample(samPoint, input.TexCoord); +float3 Phong(float ks, float exp, float3 l, float3 v, float3 n) +{ + float3 reflected = reflect(l, n); + float cosAngle = dot(reflected, v); + return ks * pow(max(0.f, cosAngle), exp) * gLightColor; +} +float3 Lambert(float kd, float3 cd) +{ + return (kd * cd) / PI; } -float4 PS_linear(VS_OUTPUT input) : SV_TARGET{ - return gDiffuseMap.Sample(samLinear, input.TexCoord); + +float3 Shade(VS_OUTPUT input) +{ + // Sample diffuse, specular, and gloss maps + float3 diffuseSample = gDiffuseMap.Sample(gSampleState, input.TexCoord).rgb; + float3 specularSample = gSpecularMap.Sample(gSampleState, input.TexCoord).rgb; + float glossSample = gGlossMap.Sample(gSampleState, input.TexCoord).x; + float3 normalSample = gNormalMap.Sample(gSampleState, input.TexCoord).rgb; + + // Compute inversed view and light directions + float3 invViewDirection = normalize(gCameraPosition - input.WorldPosition.xyz); + float3 invLightDirection = -gLightDirection; + + // Compute tangent space axes if normal mapping is used + float3 normal = input.Normal; + if (gUseNormal) { + float3 binormal = cross(input.Normal, input.Tangent); + float3x3 tangentSpaceAxis = float3x3(input.Tangent, binormal, input.Normal); + + // Sample and transform normal map + normal = float3(2.f * normalSample.x - 1.f, + 2.f * normalSample.y - 1.f, + 2.f * normalSample.z - 1.f); + normal = mul(normal, tangentSpaceAxis); + } + + // Compute Lambert diffuse lighting + float3 diffuse = Lambert(gLightIntensity, diffuseSample); + + // Compute Phong specular lighting + float ks = (specularSample.x + specularSample.y + specularSample.z) / 3.f; + float3 specular = Phong(ks, glossSample * gShininess, invLightDirection, invViewDirection, normal); + + // Compute observed area based on the cosine of the light angle + float cosAngle = dot(invLightDirection, normal); + float3 observedArea = float3(cosAngle, cosAngle, cosAngle); + + // Combine lighting components + float3 color = saturate(diffuse * observedArea + specular + gAmbient * cosAngle); + + return color; } -float4 PS_anisotropic(VS_OUTPUT input) : SV_TARGET{ - return gDiffuseMap.Sample(samAnisotropic, input.TexCoord); +float4 PS(VS_OUTPUT input) : SV_TARGET{ + return float4(Shade(input), 1.f); } -technique11 PointTechnique{ +DepthStencilState gDepthStencilState +{ + //enable + DepthEnable = true; + DepthWriteMask = ALL; + DepthFunc = LESS; + //stencil + StencilEnable = true; +}; + + +technique11 DefaultTechnique{ pass P0 { + SetDepthStencilState(gDepthStencilState, 0); SetVertexShader( CompileShader( vs_5_0, VS() ) ); SetGeometryShader( NULL ); - SetPixelShader( CompileShader( ps_5_0, PS_point() ) ); + SetPixelShader( CompileShader( ps_5_0, PS() ) ); } -} - -technique11 LinearTechnique { - pass P0 { - SetVertexShader( CompileShader( vs_5_0, VS() ) ); - SetGeometryShader( NULL ); - SetPixelShader( CompileShader( ps_5_0, PS_linear() ) ); - } -} - -technique11 AnisotropicTechnique { - pass P0 { - SetVertexShader( CompileShader( vs_5_0, VS() ) ); - SetGeometryShader( NULL ); - SetPixelShader( CompileShader( ps_5_0, PS_anisotropic() ) ); - } -} +} \ No newline at end of file diff --git a/project/src/BaseEffect.cpp b/project/src/BaseEffect.cpp new file mode 100644 index 0000000..13b927e --- /dev/null +++ b/project/src/BaseEffect.cpp @@ -0,0 +1,95 @@ +#include +#include "BaseEffect.h" + +#include +#include +#include + +BaseEffect::BaseEffect(ID3D11Device *devicePtr, const std::wstring &filePath) { + const std::ifstream file(filePath); + if (!file) + std::wcout << L"File doesn't exist" << std::endl; + + m_EffectPtr = LoadEffect(devicePtr, filePath); + m_TechniquePtr = m_EffectPtr->GetTechniqueByName("DefaultTechnique"); + + if (!m_TechniquePtr->IsValid()) + std::wcout << L"Technique is not valid" << std::endl; + + m_MatWorldViewProjVariablePtr = m_EffectPtr->GetVariableByName("gWorldViewProj")->AsMatrix(); + if (!m_MatWorldViewProjVariablePtr->IsValid()) + std::wcout << L"gWorldViewProj Matrix is not valid" << std::endl; +} + +BaseEffect::~BaseEffect() { + m_EffectPtr->Release(); + m_EffectPtr = nullptr; +} + +ID3DX11Effect *BaseEffect::LoadEffect(ID3D11Device *devicePtr, const std::wstring &filePath) { + HRESULT result; + ID3D10Blob *errorBlobPtr{nullptr}; + ID3DX11Effect *effectPtr; + + DWORD shaderFlags = 0; +#if defined( DEBUG ) || defined( _DEBUG ) + shaderFlags |= D3DCOMPILE_DEBUG; + shaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + result = D3DX11CompileEffectFromFile(filePath.c_str(), + nullptr, + nullptr, + shaderFlags, + 0, + devicePtr, + &effectPtr, + &errorBlobPtr); + + if (FAILED(result)) { + if (errorBlobPtr != nullptr) { + const char *errorsPtr = static_cast(errorBlobPtr->GetBufferPointer()); + + std::wstringstream ss; + for (UINT i{}; i < errorBlobPtr->GetBufferSize(); i++) + ss << errorsPtr[i]; + + OutputDebugStringW(ss.str().c_str()); + + errorBlobPtr->Release(); + errorBlobPtr = nullptr; + return nullptr; + } else { + std::wstringstream ss; + ss << "EffectLoader: Failed to CreateEffectFromFile!\nPath: " << filePath; + std::wcout << ss.str() << std::endl; + return nullptr; + } + } + std::cout << "Effect loaded" << std::endl; + return effectPtr; +} + +void BaseEffect::SetWorldViewProjMatrix(const dae::Matrix &matrix) { + m_MatWorldViewProjVariablePtr->SetMatrix(reinterpret_cast(&matrix)); +} + +void BaseEffect::NextSamplingState() { + +} + +void BaseEffect::SetCameraPos(const dae::Vector3 &vector3) const { + +} + +void BaseEffect::SetMaterial(Material *material) { + +} + +void BaseEffect::SetWorldMatrix(const dae::Matrix& matrix) const { + +} + +void BaseEffect::ToggleNormals() { + +} diff --git a/project/src/BaseEffect.h b/project/src/BaseEffect.h new file mode 100644 index 0000000..1fb3616 --- /dev/null +++ b/project/src/BaseEffect.h @@ -0,0 +1,47 @@ +// +// Created by Bram on 20/12/2024. +// + +#ifndef GP1_DIRECTX_BASEEFFECT_H +#define GP1_DIRECTX_BASEEFFECT_H + +#include +#include + +#include "Material.h" +#include "Matrix.h" + +class BaseEffect { +public: + BaseEffect(ID3D11Device* devicePtr, const std::wstring& filePath); + + virtual ~BaseEffect(); + + ID3DX11Effect* GetEffectPtr() const { return m_EffectPtr; } + + ID3DX11EffectTechnique* GetTechniquePtr() const { return m_TechniquePtr; } + + void SetWorldViewProjMatrix(const dae::Matrix& matrix); + + virtual void NextSamplingState(); + + virtual void SetCameraPos(const dae::Vector3 &vector3) const; + + virtual void SetMaterial(Material *material); + + virtual void SetWorldMatrix(const dae::Matrix& matrix) const; + + virtual void ToggleNormals(); + +protected: + ID3DX11Effect* m_EffectPtr{nullptr}; + ID3DX11EffectTechnique* m_TechniquePtr{}; + +private: + ID3DX11EffectMatrixVariable* m_MatWorldViewProjVariablePtr{}; + + static ID3DX11Effect* LoadEffect(ID3D11Device* devicePtr, const std::wstring& filePath); +}; + + +#endif //GP1_DIRECTX_BASEEFFECT_H diff --git a/project/src/Camera.cpp b/project/src/Camera.cpp index f6e7470..719e9c2 100644 --- a/project/src/Camera.cpp +++ b/project/src/Camera.cpp @@ -188,3 +188,7 @@ void dae::Camera::Update(const dae::Timer *pTimer) { dae::Matrix dae::Camera::GetViewProjectionMatrix() const { return viewMatrix * ProjectionMatrix; } + +const dae::Vector3 &dae::Camera::GetPosition() { + return origin; +} diff --git a/project/src/Camera.h b/project/src/Camera.h index 9dd331c..75f73ac 100644 --- a/project/src/Camera.h +++ b/project/src/Camera.h @@ -29,6 +29,8 @@ namespace dae { Matrix GetViewProjectionMatrix() const; + const Vector3 &GetPosition(); + private: Vector3 origin{}; float fovAngle{90.f}; diff --git a/project/src/Effect.cpp b/project/src/Effect.cpp index c4958e0..243d938 100644 --- a/project/src/Effect.cpp +++ b/project/src/Effect.cpp @@ -3,101 +3,156 @@ #include -Effect::Effect(ID3D11Device* devicePtr, const std::wstring& filePath) -{ - const std::ifstream file(filePath); - if(!file) - std::wcout << L"File doesn't exist" << std::endl; +Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath) + : BaseEffect(devicePtr, filePath) { - m_EffectPtr = LoadEffect(devicePtr, filePath); - m_TechniquePtr = m_EffectPtr->GetTechniqueByName("PointTechnique"); + m_LightPosVariablePtr = m_EffectPtr->GetVariableByName("gLightDirection")->AsVector(); + if(!m_LightPosVariablePtr->IsValid()) + std::wcout << L"gLightDirection Vector is not valid" << std::endl; - if(!m_TechniquePtr->IsValid()) - std::wcout << L"Technique is not valid" << std::endl; + m_SamplerVariablePtr = m_EffectPtr->GetVariableByName("gSampler")->AsSampler(); + if(!m_SamplerVariablePtr->IsValid()) + std::wcout << L"gSampler Sampler is not valid" << std::endl; - m_MatWorldViewProjVariablePtr = m_EffectPtr->GetVariableByName("gWorldViewProj")->AsMatrix(); - if(!m_MatWorldViewProjVariablePtr->IsValid()) - std::wcout << L"gWorldViewProj Matrix is not valid" << std::endl; + m_MatWorldVariablePtr = m_EffectPtr->GetVariableByName("gWorldMatrix")->AsMatrix(); + if(!m_MatWorldVariablePtr->IsValid()) + std::wcout << L"gWorld Matrix is not valid" << std::endl; + + m_DiffuseMapVariablePtr = m_EffectPtr->GetVariableByName("gDiffuseMap")->AsShaderResource(); + if(!m_DiffuseMapVariablePtr->IsValid()) + std::wcout << L"gDiffuseMap ShaderResource is not valid" << std::endl; + + m_NormalMapVariablePtr = m_EffectPtr->GetVariableByName("gNormalMap")->AsShaderResource(); + if(!m_NormalMapVariablePtr->IsValid()) + std::wcout << L"gNormalMap ShaderResource is not valid" << std::endl; + + m_SpecularMapVariablePtr = m_EffectPtr->GetVariableByName("gSpecularMap")->AsShaderResource(); + if(!m_SpecularMapVariablePtr->IsValid()) + std::wcout << L"gSpecularMap ShaderResource is not valid" << std::endl; + + m_GlossMapVariablePtr = m_EffectPtr->GetVariableByName("gGlossMap")->AsShaderResource(); + if(!m_GlossMapVariablePtr->IsValid()) + std::wcout << L"gGlossMap ShaderResource is not valid" << std::endl; + + m_CameraPosVariablePtr = m_EffectPtr->GetVariableByName("gCameraPosition")->AsVector(); + if(!m_CameraPosVariablePtr->IsValid()) + std::wcout << L"gCameraPos Vector is not valid" << std::endl; + + m_LightColorVariablePtr = m_EffectPtr->GetVariableByName("gLightColor")->AsVector(); + if(!m_LightColorVariablePtr->IsValid()) + std::wcout << L"gLightColor Vector is not valid" << std::endl; + + m_UseNormalMapVariablePtr = m_EffectPtr->GetVariableByName("gUseNormal")->AsScalar(); + if(!m_UseNormalMapVariablePtr->IsValid()) + std::wcout << L"gUseNormalMap Scalar is not valid" << std::endl; + + m_UseNormalMapVariablePtr->SetBool(m_UseNormalMap); + + + constexpr int vectorSize{ 4 }; + constexpr float lightDirection[vectorSize]{ .577f, -.577f, .577f, 0.f }; + m_LightPosVariablePtr->SetFloatVector(lightDirection); + + constexpr float lightColor[vectorSize]{ 1.f, 1.f, 1.f, 1.f }; + m_LightColorVariablePtr->SetFloatVector(lightColor); + + this->InitSamplers(devicePtr); } -Effect::~Effect() -{ - m_EffectPtr->Release(); - m_EffectPtr = nullptr; +Effect::~Effect() { + m_MatWorldVariablePtr->Release(); + m_MatWorldVariablePtr = nullptr; -// m_TechniquePtr->Release(); -// m_TechniquePtr = nullptr; -} + m_DiffuseMapVariablePtr->Release(); + m_DiffuseMapVariablePtr = nullptr; -ID3DX11Effect* Effect::LoadEffect(ID3D11Device* devicePtr, const std::wstring& filePath) { - HRESULT result; - ID3D10Blob *errorBlobPtr{nullptr}; - ID3DX11Effect *effectPtr; + m_NormalMapVariablePtr->Release(); + m_NormalMapVariablePtr = nullptr; - DWORD shaderFlags = 0; -#if defined( DEBUG ) || defined( _DEBUG ) - shaderFlags |= D3DCOMPILE_DEBUG; - shaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION; -#endif + m_SpecularMapVariablePtr->Release(); + m_SpecularMapVariablePtr = nullptr; - result = D3DX11CompileEffectFromFile(filePath.c_str(), - nullptr, - nullptr, - shaderFlags, - 0, - devicePtr, - &effectPtr, - &errorBlobPtr); + m_GlossMapVariablePtr->Release(); + m_GlossMapVariablePtr = nullptr; - if (FAILED(result)) { - if (errorBlobPtr != nullptr) { - const char *errorsPtr = static_cast(errorBlobPtr->GetBufferPointer()); + m_CameraPosVariablePtr->Release(); + m_CameraPosVariablePtr = nullptr; - std::wstringstream ss; - for (UINT i{}; i < errorBlobPtr->GetBufferSize(); i++) - ss << errorsPtr[i]; + m_LightPosVariablePtr->Release(); + m_LightPosVariablePtr = nullptr; - OutputDebugStringW(ss.str().c_str()); - errorBlobPtr->Release(); - errorBlobPtr = nullptr; + m_LightColorVariablePtr->Release(); + m_LightColorVariablePtr = nullptr; - return nullptr; - } else { - std::wstringstream ss; - ss << "EffectLoader: Failed to CreateEffectFromFile!\nPath: " << filePath; - std::wcout << ss.str() << std::endl; - return nullptr; - } + m_UseNormalMapVariablePtr->Release(); + m_UseNormalMapVariablePtr = nullptr; + + m_SamplerVariablePtr->Release(); + m_SamplerVariablePtr = nullptr; + + for(auto sampler : m_SamplerStates){ + sampler->Release(); } - std::cout << "Effect loaded" << std::endl; - return effectPtr; } -void Effect::SetWorldViewProjMatrix(const dae::Matrix &matrix) { - m_MatWorldViewProjVariablePtr->SetMatrix(reinterpret_cast(&matrix)); +void Effect::SetWorldMatrix(const dae::Matrix &world) const { + m_MatWorldVariablePtr->SetMatrix(reinterpret_cast(&world)); } -void Effect::SetMaterial(const Material &material) { - if(material.diffuseTexturePtr) - m_EffectPtr->GetVariableByName("gDiffuseMap")->AsShaderResource()->SetResource(material.diffuseTexturePtr->GetSrv()); +void Effect::SetMaterial(Material* material) { + if(material->diffuseTexturePtr) + m_DiffuseMapVariablePtr->SetResource(material->diffuseTexturePtr->GetSrv()); + if(material->normalTexturePtr) + m_NormalMapVariablePtr->SetResource(material->normalTexturePtr->GetSrv()); + if(material->specularTexturePtr) + m_SpecularMapVariablePtr->SetResource(material->specularTexturePtr->GetSrv()); + if(material->glossTexturePtr) + m_GlossMapVariablePtr->SetResource(material->glossTexturePtr->GetSrv()); } -void Effect::NextTechnique() { - switch (m_TechniqueType) { + +void Effect::SetCameraPos(const dae::Vector3 &pos) const { + m_CameraPosVariablePtr->SetFloatVector(reinterpret_cast(&pos)); +} + +void Effect::NextSamplingState() { + switch(m_TechniqueType){ case TechniqueType::Point: m_TechniqueType = TechniqueType::Linear; - m_TechniquePtr = m_EffectPtr->GetTechniqueByName("LinearTechnique"); std::cout << "Linear" << std::endl; break; case TechniqueType::Linear: m_TechniqueType = TechniqueType::Anisotropic; - m_TechniquePtr = m_EffectPtr->GetTechniqueByName("AnisotropicTechnique"); std::cout << "Anisotropic" << std::endl; break; case TechniqueType::Anisotropic: m_TechniqueType = TechniqueType::Point; - m_TechniquePtr = m_EffectPtr->GetTechniqueByName("PointTechnique"); std::cout << "Point" << std::endl; break; } + m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast(m_TechniqueType)]); +} + +void Effect::ToggleNormals() { + m_UseNormalMap = !m_UseNormalMap; + m_UseNormalMapVariablePtr->SetBool(m_UseNormalMap); +} + +void Effect::InitSamplers(ID3D11Device *devicePtr) { + D3D11_SAMPLER_DESC samplerDesc{}; + samplerDesc.Filter = D3D11_FILTER_ANISOTROPIC; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + + devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast(TechniqueType::Anisotropic)]); + + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast(TechniqueType::Linear)]); + + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast(TechniqueType::Point)]); + + m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast(m_TechniqueType)]); } diff --git a/project/src/Effect.h b/project/src/Effect.h index 86fec08..69f61c2 100644 --- a/project/src/Effect.h +++ b/project/src/Effect.h @@ -1,36 +1,53 @@ #pragma once -#include "Mesh.h" +#include "BaseEffect.h" +#include -enum class TechniqueType{ - Point, - Linear, - Anisotropic +enum class TechniqueType { + Point = 0, + Linear = 1, + Anisotropic = 2 }; -class Effect final -{ - static inline constexpr char TECHNIQUE_NAME[] = "DefaultTechnique"; + +class Effect: public BaseEffect { public: - Effect(ID3D11Device* devicePtr, const std::wstring& filePath); - ~Effect(); + Effect(ID3D11Device *devicePtr, const std::wstring &filePath); - inline ID3DX11Effect* GetEffectPtr() const { return m_EffectPtr; } - inline ID3DX11EffectTechnique* GetTechniquePtr() const { return m_TechniquePtr; } + virtual ~Effect() override; - void SetWorldViewProjMatrix(const dae::Matrix &matrix); + void SetWorldMatrix(const dae::Matrix &world) const override; - void SetMaterial(const Material &material); + void SetCameraPos(const dae::Vector3 &pos) const override; - void NextTechnique(); + void SetMaterial(Material *material); + + void ToggleNormals() override; + + void NextSamplingState() override; private: - ID3DX11Effect* m_EffectPtr{ nullptr }; - ID3DX11EffectTechnique* m_TechniquePtr{}; - static ID3DX11Effect* LoadEffect(ID3D11Device* devicePtr, const std::wstring& filePath); + void InitSamplers(ID3D11Device* devicePtr); - ID3DX11EffectMatrixVariable* m_MatWorldViewProjVariablePtr{}; + ID3DX11EffectMatrixVariable *m_MatWorldVariablePtr{}; - TechniqueType m_TechniqueType{ TechniqueType::Linear }; + ID3DX11EffectShaderResourceVariable *m_DiffuseMapVariablePtr{}; + ID3DX11EffectShaderResourceVariable *m_NormalMapVariablePtr{}; + ID3DX11EffectShaderResourceVariable *m_SpecularMapVariablePtr{}; + ID3DX11EffectShaderResourceVariable *m_GlossMapVariablePtr{}; + + ID3DX11EffectVectorVariable *m_CameraPosVariablePtr{}; + ID3DX11EffectVectorVariable *m_LightPosVariablePtr{}; + ID3DX11EffectVectorVariable *m_LightColorVariablePtr{}; + + ID3DX11EffectScalarVariable *m_UseNormalMapVariablePtr{}; + + ID3DX11EffectSamplerVariable *m_SamplerVariablePtr{}; + + TechniqueType m_TechniqueType{TechniqueType::Linear}; + + std::array m_SamplerStates{}; + + bool m_UseNormalMap{true}; }; diff --git a/project/src/FireEffect.cpp b/project/src/FireEffect.cpp new file mode 100644 index 0000000..90ebadb --- /dev/null +++ b/project/src/FireEffect.cpp @@ -0,0 +1,23 @@ +// +// Created by Bram on 20/12/2024. +// + +#include "FireEffect.h" + +#include + +FireEffect::FireEffect(ID3D11Device *devicePtr, const std::wstring &filePath) : BaseEffect(devicePtr, filePath) { + m_DiffuseMapVariablePtr = m_EffectPtr->GetVariableByName("gDiffuseMap")->AsShaderResource(); + if (!m_DiffuseMapVariablePtr->IsValid()) + std::wcout << L"gDiffuseMap ShaderResource is not valid" << std::endl; +} + +FireEffect::~FireEffect() { + m_DiffuseMapVariablePtr->Release(); + m_DiffuseMapVariablePtr = nullptr; +} + +void FireEffect::SetMaterial(Material *material) { + if(material->diffuseTexturePtr) + m_DiffuseMapVariablePtr->SetResource(material->diffuseTexturePtr->GetSrv()); +} \ No newline at end of file diff --git a/project/src/FireEffect.h b/project/src/FireEffect.h new file mode 100644 index 0000000..4bab1c9 --- /dev/null +++ b/project/src/FireEffect.h @@ -0,0 +1,24 @@ +// +// Created by Bram on 20/12/2024. +// + +#ifndef GP1_DIRECTX_FIREEFFECT_H +#define GP1_DIRECTX_FIREEFFECT_H + + +#include "BaseEffect.h" + +class FireEffect: public BaseEffect { +public: + FireEffect(ID3D11Device *devicePtr, const std::wstring &filePath); + + virtual ~FireEffect() override; + + void SetMaterial(Material *material) override; + +private: + ID3DX11EffectShaderResourceVariable *m_DiffuseMapVariablePtr{}; +}; + + +#endif //GP1_DIRECTX_FIREEFFECT_H diff --git a/project/src/GamePadController.cpp b/project/src/GamePadController.cpp index ebcff35..73c50af 100644 --- a/project/src/GamePadController.cpp +++ b/project/src/GamePadController.cpp @@ -2,6 +2,7 @@ // Created by Bram on 11/12/2024. // +#include #include "GamePadController.h" GamePadController::GamePadController() = default; @@ -26,6 +27,44 @@ void GamePadController::Init() { } void GamePadController::Update() { + //Check for new controllers + const int numJoysticks = SDL_NumJoysticks(); + if(numJoysticks > m_pGameControllers.size()){ + for (int i = 0; i < numJoysticks; i++) { + if (SDL_IsGameController(i)) { + bool bFound = false; + for (auto pController : m_pGameControllers) { + if (SDL_GameControllerGetJoystick(pController) == SDL_JoystickFromInstanceID(i)) { + bFound = true; + break; + } + } + + if (!bFound) { + SDL_GameController *pController = SDL_GameControllerOpen(i); + if (pController) { + m_pGameControllers.push_back(pController); + m_GamePads.push_back(GamePad()); + + std::cout << "New Controller Connected" << std::endl; + } + } + } + } + } + + for (int i = 0; i < m_pGameControllers.size(); ++i) { + SDL_GameController *pController = m_pGameControllers[i]; + if (!SDL_GameControllerGetAttached(pController)) { + SDL_GameControllerClose(pController); + m_pGameControllers.erase(m_pGameControllers.begin() + i); + m_GamePads.erase(m_GamePads.begin() + i); + std::cout << "Controller Disconnected" << std::endl; + --i; // Adjust index after removing the controller + } + } + + for (int i = 0; i < m_pGameControllers.size(); i++) { SDL_GameController *pController = m_pGameControllers[i]; GamePad &gamePad = m_GamePads[i]; diff --git a/project/src/Material.cpp b/project/src/Material.cpp new file mode 100644 index 0000000..c2f8f9b --- /dev/null +++ b/project/src/Material.cpp @@ -0,0 +1 @@ +#include "Material.h" diff --git a/project/src/Material.h b/project/src/Material.h new file mode 100644 index 0000000..30b86b4 --- /dev/null +++ b/project/src/Material.h @@ -0,0 +1,22 @@ +#ifndef GP1_DIRECTX_MATERIAL_H +#define GP1_DIRECTX_MATERIAL_H + + +#include "Texture.h" + +struct Material { + Texture *diffuseTexturePtr{nullptr}; + Texture *normalTexturePtr{nullptr}; + Texture *specularTexturePtr{nullptr}; + Texture *glossTexturePtr{nullptr}; + + ~Material() { + delete diffuseTexturePtr; + delete normalTexturePtr; + delete specularTexturePtr; + delete glossTexturePtr; + } +}; + + +#endif //GP1_DIRECTX_MATERIAL_H diff --git a/project/src/Mesh.cpp b/project/src/Mesh.cpp index 5482b7a..4b91413 100644 --- a/project/src/Mesh.cpp +++ b/project/src/Mesh.cpp @@ -1,26 +1,27 @@ #include +#include #include "pch.h" #include "Mesh.h" #include "Effect.h" -Mesh::Mesh(ID3D11Device *devicePtr, const std::vector &verticesIn, const std::vector &indices, const Material &material) : - m_EffectPtr(new Effect{devicePtr, L"resources/PosCol3D.fx"}), +Mesh::Mesh(ID3D11Device *devicePtr, const std::vector &verticesIn, const std::vector &indices, std::shared_ptr material, BaseEffect* effectPtr) : + m_EffectPtr(effectPtr), m_InputLayoutPtr(nullptr), m_VertexBufferPtr(nullptr), m_IndexBufferPtr(nullptr), m_VerticesIn(verticesIn), m_Indices(indices), m_IndicesCount(static_cast(m_Indices.size())), - m_Material(material) { + m_Material(std::move(material)) { HRESULT result; D3D11_BUFFER_DESC bufferDesc{}; D3D11_SUBRESOURCE_DATA subresourceData{}; - m_EffectPtr->SetMaterial(m_Material); + m_EffectPtr->SetMaterial(m_Material.get()); //Create vertex layout - static constexpr uint32_t vertexElementCount{3}; + static constexpr uint32_t vertexElementCount{4}; D3D11_INPUT_ELEMENT_DESC vertexDesc[vertexElementCount]{}; vertexDesc[0].SemanticName = "POSITION"; @@ -28,18 +29,20 @@ Mesh::Mesh(ID3D11Device *devicePtr, const std::vector &verticesIn, con vertexDesc[0].AlignedByteOffset = 0; vertexDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - vertexDesc[1].SemanticName = "COLOR"; - vertexDesc[1].Format = DXGI_FORMAT_R32G32B32_FLOAT; - vertexDesc[1].AlignedByteOffset = offsetof(VertexIn, color); - + vertexDesc[1].SemanticName = "TEXCOORD"; + vertexDesc[1].Format = DXGI_FORMAT_R32G32_FLOAT; + vertexDesc[1].AlignedByteOffset = offsetof(VertexIn, uv); vertexDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - vertexDesc[2].SemanticName = "TEXCOORD"; - vertexDesc[2].Format = DXGI_FORMAT_R32G32_FLOAT; - vertexDesc[2].AlignedByteOffset = offsetof(VertexIn, uv); + vertexDesc[2].SemanticName = "NORMAL"; + vertexDesc[2].Format = DXGI_FORMAT_R32G32B32_FLOAT; + vertexDesc[2].AlignedByteOffset = offsetof(VertexIn, normal); vertexDesc[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - + vertexDesc[3].SemanticName = "TANGENT"; + vertexDesc[3].Format = DXGI_FORMAT_R32G32B32_FLOAT; + vertexDesc[3].AlignedByteOffset = offsetof(VertexIn, tangent); + vertexDesc[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; //Create input layout D3DX11_PASS_DESC passDesc{}; @@ -57,7 +60,7 @@ Mesh::Mesh(ID3D11Device *devicePtr, const std::vector &verticesIn, con //Create vertex buffer bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; - bufferDesc.ByteWidth = sizeof(verticesIn) * static_cast(verticesIn.size()); + bufferDesc.ByteWidth = sizeof(VertexIn) * static_cast(verticesIn.size()); bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufferDesc.CPUAccessFlags = 0; bufferDesc.MiscFlags = 0; @@ -94,6 +97,7 @@ Mesh::~Mesh() { void Mesh::Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldViewProj) const { m_EffectPtr->SetWorldViewProjMatrix(worldViewProj); + m_EffectPtr->SetWorldMatrix(m_WorldMatrix); //1. Set primitive topology deviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); @@ -117,6 +121,18 @@ void Mesh::Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldView } } -void Mesh::NextTechnique() { - m_EffectPtr->NextTechnique(); +void Mesh::NextSamplingState() { + m_EffectPtr->NextSamplingState(); +} + +void Mesh::SetCameraPos(const Vector3 &pos) const { + m_EffectPtr->SetCameraPos(pos); +} + +void Mesh::SetWorldMatrix(const Matrix &matrix) { + m_WorldMatrix = matrix; +} + +void Mesh::ToggleNormals() { + m_EffectPtr->ToggleNormals(); } diff --git a/project/src/Mesh.h b/project/src/Mesh.h index 8da7b10..ed23ae6 100644 --- a/project/src/Mesh.h +++ b/project/src/Mesh.h @@ -1,63 +1,69 @@ #pragma once #include "Texture.h" +#include "BaseEffect.h" + +#include +#include class Effect; + using namespace dae; struct VertexIn; struct VertexOut; -struct Material{ - Texture* diffuseTexturePtr{ nullptr }; - ~Material(){ - if(diffuseTexturePtr){ - delete diffuseTexturePtr; - } - } -}; -class Mesh final -{ +class Mesh final { public: - Mesh(ID3D11Device* devicePtr, const std::vector& verticesIn, const std::vector& indices, const Material& material); + Mesh(ID3D11Device *devicePtr, const std::vector &verticesIn, const std::vector &indices, + std::shared_ptr material, BaseEffect* effectPtr); + ~Mesh(); - void Render(ID3D11DeviceContext* deviceContextPtr, const Matrix& worldViewProj) const; + void Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldViewProj) const; - void NextTechnique(); + void SetCameraPos(const Vector3 &pos) const; + + Matrix GetWorldMatrix() const { return m_WorldMatrix; } + + void ToggleNormals(); + + void NextSamplingState(); + + void SetWorldMatrix(const Matrix &matrix); private: - Effect* m_EffectPtr; + BaseEffect *m_EffectPtr; - ID3D11InputLayout* m_InputLayoutPtr; - ID3D11Buffer* m_VertexBufferPtr; - ID3D11Buffer* m_IndexBufferPtr; + Matrix m_WorldMatrix{}; + + ID3D11InputLayout *m_InputLayoutPtr; + ID3D11Buffer *m_VertexBufferPtr; + ID3D11Buffer *m_IndexBufferPtr; std::vector m_VerticesIn; std::vector m_Indices; UINT m_IndicesCount; - Material m_Material{}; + std::shared_ptr m_Material{}; }; -struct VertexIn -{ +struct VertexIn { Vector3 position{}; - Vector3 color{}; Vector2 uv{}; -// Vector3 normal{}; -// Vector3 tangent{}; + Vector3 normal{}; + Vector3 tangent{}; }; -struct VertexOut -{ +struct VertexOut { Vector4 position{}; - Vector3 color{}; + ColorRGB color{}; Vector2 uv{}; -// Vector3 normal{}; - + Vector3 normal{}; + Vector3 tangent{}; + Vector3 viewDir{}; }; diff --git a/project/src/Renderer.cpp b/project/src/Renderer.cpp index 1611f61..f7d1704 100644 --- a/project/src/Renderer.cpp +++ b/project/src/Renderer.cpp @@ -2,6 +2,9 @@ #include "Renderer.h" #include "Mesh.h" #include "Utils.h" +#include "Texture.h" +#include "Effect.h" +#include "FireEffect.h" namespace dae { @@ -18,11 +21,15 @@ namespace dae { } else { std::cout << "DirectX initialization failed!\n"; } + + InitializeSDLRasterizer(); + std::vector vertices{}; std::vector indices{}; - if (Utils::ParseOBJNew("resources/scene.obj", vertices, indices, false)) { + if (Utils::ParseOBJNew("resources/vehicle.obj", vertices, indices, false)) { std::cout << "Model Loaded" << std::endl; + } else { std::cout << "Model failed to load" << std::endl; assert(true && "Model failed to load"); @@ -30,11 +37,36 @@ namespace dae { std::cout << "Vertices: " << vertices.size() << " Indices: " << indices.size() << std::endl; - m_material.diffuseTexturePtr = Texture::LoadFromFile("resources/uv_grid_2.png", m_DevicePtr); - m_mesh = new Mesh(m_DevicePtr, vertices, indices, m_material); + std::shared_ptr vehicleMaterial = std::make_shared(); + vehicleMaterial->diffuseTexturePtr = Texture::LoadFromFile("resources/vehicle_diffuse.png", m_DevicePtr); + vehicleMaterial->normalTexturePtr = Texture::LoadFromFile("resources/vehicle_normal.png", m_DevicePtr); + vehicleMaterial->specularTexturePtr = Texture::LoadFromFile("resources/vehicle_specular.png", m_DevicePtr); + vehicleMaterial->glossTexturePtr = Texture::LoadFromFile("resources/vehicle_gloss.png", m_DevicePtr); - m_Camera = Camera(Vector3(0.f, 0.f, -5.f), 90.f); - m_Camera.Initialize(90.f, Vector3(0.f, 0.f, -5.f), 1.f); + Effect* effect = new Effect(m_DevicePtr, L"resources/PosCol3D.fx"); + m_meshes.push_back(new Mesh(m_DevicePtr, vertices, indices, vehicleMaterial, effect)); + + + + indices.clear(); + vertices.clear(); + if(Utils::ParseOBJNew("resources/fireFX.obj", vertices, indices, false)){ + std::cout << "Model Loaded" << std::endl; + } else { + std::cout << "Model failed to load" << std::endl; + assert(true && "Model failed to load"); + } + + std::shared_ptr FireMaterial = std::make_shared(); + FireMaterial->diffuseTexturePtr = Texture::LoadFromFile("resources/fireFX_diffuse.png", m_DevicePtr); + + FireEffect* fireEffect = new FireEffect(m_DevicePtr, L"resources/Fire.fx"); + m_meshes.push_back(new Mesh(m_DevicePtr, vertices, indices, FireMaterial, fireEffect)); + + + float aspectRatio = static_cast(m_Width) / static_cast(m_Height); + m_Camera = Camera({.0f, 5.0f, -64.f}, 45.f); + m_Camera.Initialize(45.f, {.0f, 5.0f, -64.f}, aspectRatio); } Renderer::~Renderer() { @@ -54,34 +86,61 @@ namespace dae { m_DevicePtr->Release(); - delete m_mesh; + for (auto mesh: m_meshes) { + delete mesh; + } } void Renderer::Update(const Timer *pTimer) { m_Camera.Update(pTimer); - } + for (auto mesh: m_meshes) { + mesh->SetCameraPos(m_Camera.GetPosition()); + } + if (m_Rotating) { + m_currentRotation += pTimer->GetElapsed(); + Matrix world = Matrix::CreateRotationY(m_currentRotation); + for (auto mesh: m_meshes) { + mesh->SetWorldMatrix(world); + } + } + } void Renderer::Render() const { if (!m_IsInitialized) return; + if (m_backendType == Backendtype::DirectX) { - //Clear back buffer - const float clearColor[] = {.39f, .59f, .93f, 1.f}; - m_DeviceContextPtr->ClearRenderTargetView(m_RenderTargetViewPtr, clearColor); - m_DeviceContextPtr->ClearDepthStencilView(m_DepthStencilViewPtr, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); + //Clear back buffer + const float clearColor[] = {1.f / 255.f, 0.f / 255.f, 76.f / 255.f, 1.f}; + m_DeviceContextPtr->ClearRenderTargetView(m_RenderTargetViewPtr, clearColor); + m_DeviceContextPtr->ClearDepthStencilView(m_DepthStencilViewPtr, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); - Matrix worldViewProj = m_Camera.GetViewProjectionMatrix(); - Matrix modelMatrix{}; + Matrix viewProjMatrix = m_Camera.GetViewProjectionMatrix(); + for (auto mesh: m_meshes) { + Matrix modelMatrix = mesh->GetWorldMatrix(); + Matrix worldViewProjMatrix = modelMatrix * viewProjMatrix; + mesh->Render(m_DeviceContextPtr, worldViewProjMatrix); + } - //Render - m_mesh->Render(m_DeviceContextPtr, worldViewProj * modelMatrix); + //Present + m_SwapChainPtr->Present(0, 0); + } else { + SDL_FillRect(m_pBackBuffer, nullptr, Uint32(255 << 24) + Uint32(100 << 16) + Uint32(100 << 8) + Uint32(100)); - //Present - m_SwapChainPtr->Present(0, 0); + //Lock BackBuffer + for (int x = 0; x < 100; ++x) { + for (int y = 0; y < 100; ++y) { + m_pBackBufferPixels[(x + 100) + (y + 150) * m_Width] = SDL_MapRGB(m_pBackBuffer->format, 255, 0, 0); + } + } + + SDL_BlitSurface(m_pBackBuffer, nullptr, m_pFrontBuffer, nullptr); + SDL_UpdateWindowSurface(m_pWindow); + } } @@ -194,7 +253,41 @@ namespace dae { return S_OK; } - void Renderer::SwitchTechnique() { - m_mesh->NextTechnique(); + + void Renderer::InitializeSDLRasterizer() { + m_pFrontBuffer = SDL_GetWindowSurface(m_pWindow); + m_pBackBuffer = SDL_CreateRGBSurface(0, m_Width, m_Height, 32, 0, 0, 0, 0); + m_pBackBufferPixels = (uint32_t *) m_pBackBuffer->pixels; + +// m_pDepthBufferPixels = new float[m_Width * m_Height]; + + } + + void Renderer::SwitchBackend() { + if (m_backendType == Backendtype::DirectX) { + m_backendType = Backendtype::SDL; + } else { + m_backendType = Backendtype::DirectX; + } + } + + void Renderer::NextSamplingState() { + for(auto mesh: m_meshes){ + mesh->NextSamplingState(); + } + } + + void Renderer::ToggleNormals() { + for(auto mesh: m_meshes){ + mesh->ToggleNormals(); + } + } + + void Renderer::ToggleRotation() { + m_Rotating = !m_Rotating; + } + + void Renderer::ToggleUniformClearColor() { + m_UniformClearColor = !m_UniformClearColor; } } diff --git a/project/src/Renderer.h b/project/src/Renderer.h index f9d71a8..b007392 100644 --- a/project/src/Renderer.h +++ b/project/src/Renderer.h @@ -6,6 +6,11 @@ struct SDL_Window; struct SDL_Surface; +enum class Backendtype { + DirectX, + SDL +}; + namespace dae { class Renderer final @@ -23,9 +28,16 @@ namespace dae void Render() const; //Switching Functions - void SwitchTechnique(); + void NextSamplingState(); + void ToggleNormals(); - private: + void SwitchBackend(); + + void ToggleRotation(); + + void ToggleUniformClearColor(); + + private: SDL_Window* m_pWindow{}; int m_Width{}; @@ -35,6 +47,7 @@ namespace dae //DIRECTX HRESULT InitializeDirectX(); + void InitializeSDLRasterizer(); ID3D11Device* m_DevicePtr{}; ID3D11DeviceContext* m_DeviceContextPtr{}; @@ -44,11 +57,21 @@ namespace dae ID3D11Resource* m_RenderTargetBufferPtr{}; ID3D11RenderTargetView* m_RenderTargetViewPtr{}; + SDL_Surface* m_pFrontBuffer{ nullptr }; + SDL_Surface* m_pBackBuffer{ nullptr }; + uint32_t* m_pBackBufferPixels{}; - Mesh* m_mesh{ nullptr }; - Material m_material{}; + + std::vector m_meshes{}; + std::vector> m_materials{}; + + Backendtype m_backendType{ Backendtype::DirectX }; Camera m_Camera{}; + bool m_Rotating{ false }; + float m_currentRotation{}; + bool m_UniformClearColor{ false }; + }; } diff --git a/project/src/Texture.cpp b/project/src/Texture.cpp index 3eec376..b464220 100644 --- a/project/src/Texture.cpp +++ b/project/src/Texture.cpp @@ -12,7 +12,7 @@ Texture *Texture::LoadFromFile(const std::string &path, ID3D11Device *devicePtr) return nullptr; } - Texture *texture = new Texture(surface, devicePtr); + auto *texture = new Texture(surface, devicePtr); return texture; } diff --git a/project/src/Utils.h b/project/src/Utils.h index a1a56a9..dd4c365 100644 --- a/project/src/Utils.h +++ b/project/src/Utils.h @@ -87,7 +87,7 @@ namespace dae { vertices.push_back(vertex); tempIndices[iFace] = uint32_t(vertices.size()) - 1; - //indices.push_back(uint32_t(vertices.size()) - 1); +// indices.push_back(uint32_t(vertices.size()) - 1); } indices.push_back(tempIndices[0]); @@ -103,42 +103,42 @@ namespace dae { file.ignore(1000, '\n'); } -// //Cheap Tangent Calculations -// for (uint32_t i = 0; i < indices.size(); i += 3) { -// uint32_t index0 = indices[i]; -// uint32_t index1 = indices[size_t(i) + 1]; -// uint32_t index2 = indices[size_t(i) + 2]; -// -// const Vector3 &p0 = vertices[index0].position; -// const Vector3 &p1 = vertices[index1].position; -// const Vector3 &p2 = vertices[index2].position; -// const Vector2 &uv0 = vertices[index0].uv; -// const Vector2 &uv1 = vertices[index1].uv; -// const Vector2 &uv2 = vertices[index2].uv; -// -// const Vector3 edge0 = p1 - p0; -// const Vector3 edge1 = p2 - p0; -// const Vector2 diffX = Vector2(uv1.x - uv0.x, uv2.x - uv0.x); -// const Vector2 diffY = Vector2(uv1.y - uv0.y, uv2.y - uv0.y); -// float r = 1.f / Vector2::Cross(diffX, diffY); -// -// Vector3 tangent = (edge0 * diffY.y - edge1 * diffY.x) * r; -// vertices[index0].tangent += tangent; -// vertices[index1].tangent += tangent; -// vertices[index2].tangent += tangent; -// } -// -// //Fix the tangents per vertex now because we accumulated -// for (auto &v: vertices) { -// v.tangent = Vector3::Reject(v.tangent, v.normal).Normalized(); -// -// if (flipAxisAndWinding) { -// v.position.z *= -1.f; -// v.normal.z *= -1.f; -// v.tangent.z *= -1.f; -// } -// -// } + //Cheap Tangent Calculations + for (uint32_t i = 0; i < indices.size(); i += 3) { + uint32_t index0 = indices[i]; + uint32_t index1 = indices[size_t(i) + 1]; + uint32_t index2 = indices[size_t(i) + 2]; + + const Vector3 &p0 = vertices[index0].position; + const Vector3 &p1 = vertices[index1].position; + const Vector3 &p2 = vertices[index2].position; + const Vector2 &uv0 = vertices[index0].uv; + const Vector2 &uv1 = vertices[index1].uv; + const Vector2 &uv2 = vertices[index2].uv; + + const Vector3 edge0 = p1 - p0; + const Vector3 edge1 = p2 - p0; + const Vector2 diffX = Vector2(uv1.x - uv0.x, uv2.x - uv0.x); + const Vector2 diffY = Vector2(uv1.y - uv0.y, uv2.y - uv0.y); + float r = 1.f / Vector2::Cross(diffX, diffY); + + Vector3 tangent = (edge0 * diffY.y - edge1 * diffY.x) * r; + vertices[index0].tangent += tangent; + vertices[index1].tangent += tangent; + vertices[index2].tangent += tangent; + } + + //Fix the tangents per vertex now because we accumulated + for (auto &v: vertices) { + v.tangent = Vector3::Reject(v.tangent, v.normal).Normalized(); + + if (flipAxisAndWinding) { + v.position.z *= -1.f; + v.normal.z *= -1.f; + v.tangent.z *= -1.f; + } + + } return true; } @@ -169,7 +169,7 @@ namespace dae { size_t index_offset = 0; for (size_t f = 0; f < shape.mesh.num_face_vertices.size(); f++) { - size_t fv = size_t(shape.mesh.num_face_vertices[f]); + auto fv = size_t(shape.mesh.num_face_vertices[f]); if (fv != 3) { std::cerr << "Error: Only triangular faces are supported." << std::endl; @@ -177,6 +177,7 @@ namespace dae { } uint32_t tempIndices[3]; + VertexIn tempVertices[3]; for (size_t v = 0; v < fv; v++) { tinyobj::index_t idx = shape.mesh.indices[index_offset + v]; @@ -202,16 +203,17 @@ namespace dae { } if (idx.normal_index >= 0) { -// vertex.normal = Vector3( -// attrib.normals[3 * idx.normal_index + 0], -// attrib.normals[3 * idx.normal_index + 1], -// attrib.normals[3 * idx.normal_index + 2] -// ); -// if (flipAxisAndWinding) { -// vertex.normal.z *= -1.0f; -// } + vertex.normal = Vector3( + attrib.normals[3 * idx.normal_index + 0], + attrib.normals[3 * idx.normal_index + 1], + attrib.normals[3 * idx.normal_index + 2] + ); + if (flipAxisAndWinding) { + vertex.normal.z *= -1.0f; + } } + tempVertices[v] = vertex; vertices.push_back(vertex); tempIndices[v] = static_cast(vertices.size() - 1); } @@ -225,10 +227,30 @@ namespace dae { indices.push_back(tempIndices[2]); } + const Vector3 &pos0 = tempVertices[0].position; + const Vector3 &pos1 = tempVertices[1].position; + const Vector3 &pos2 = tempVertices[2].position; + + const Vector2 &uv0 = tempVertices[0].uv; + const Vector2 &uv1 = tempVertices[1].uv; + const Vector2 &uv2 = tempVertices[2].uv; + + Vector3 edge1 = pos1 - pos0; + Vector3 edge2 = pos2 - pos0; + + Vector2 deltaUV1 = uv1 - uv0; + Vector2 deltaUV2 = uv2 - uv0; + + float temp = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x); + + Vector3 tangent = temp * (deltaUV2.y * edge1 - deltaUV1.y * edge2); + tangent = tangent.Normalized(); + + for (size_t v = 0; v < fv; v++) { + vertices[tempIndices[v]].tangent = tangent; + } + index_offset += fv; - - shape.mesh.material_ids[f]; - } } diff --git a/project/src/main.cpp b/project/src/main.cpp index 1afd05a..d7cc7c4 100644 --- a/project/src/main.cpp +++ b/project/src/main.cpp @@ -42,16 +42,6 @@ int main(int argc, char *args[]) { int joysticks = SDL_NumJoysticks(); std::cout << "Number of joysticks connected: " << joysticks << std::endl; - // If there are joysticks connected, open one up for reading - if (joysticks > 0) { - if (SDL_JoystickOpen(0) == NULL) { - std::cerr << "Failed to open joystick 0" << std::endl; - return -1; - } - } else { - std::cout << "No joysticks connected" << std::endl; - } - GamePadController::GetInstance().Init(); @@ -71,14 +61,59 @@ int main(int argc, char *args[]) { case SDL_QUIT: isLooping = false; break; - case SDL_KEYUP: - //Test for a key - //if (e.key.keysym.scancode == SDL_SCANCODE_X) + case SDL_KEYUP: { + SDL_Scancode scancode = e.key.keysym.scancode; + if(scancode == SDL_SCANCODE_F1){ + //Switch backend + pRenderer->SwitchBackend(); + } + if(scancode == SDL_SCANCODE_F2){ + //toggle rotation + pRenderer->ToggleRotation(); + } + if(scancode == SDL_SCANCODE_F9){ + // Cycle Cull mode + } + if(scancode == SDL_SCANCODE_F10){ + // Toggle Uniform Clear Color + pRenderer->ToggleUniformClearColor(); + } + if(scancode == SDL_SCANCODE_F11){ + // toggle Print fps + } + + //Hardware + if (scancode == SDL_SCANCODE_F3){ + // Toggle FireFX mesh + } + if (scancode == SDL_SCANCODE_F4){ + //Toggle texture sampling states + pRenderer->NextSamplingState(); + } + //Software + if(scancode == SDL_SCANCODE_F5){ + //Cycle shading mode + } + if(scancode == SDL_SCANCODE_F6){ + //Toggle normal mapping + } + if(scancode == SDL_SCANCODE_F7){ + //Toggle Depth Buffer + } + if(scancode == SDL_SCANCODE_F8) { + //Toggle BoundingBox + } + if (e.key.keysym.scancode == SDL_SCANCODE_F2) { - pRenderer->SwitchTechnique(); + } + if (e.key.keysym.scancode == SDL_SCANCODE_F3) { + + } + if (e.key.keysym.scancode == SDL_SCANCODE_F4) { + pRenderer->ToggleNormals(); } break; - + } default: break; }