Final DirectX

This commit is contained in:
2024-12-24 15:25:59 +01:00
parent 8a19a2afa1
commit b4d49a0dff
21 changed files with 942 additions and 267 deletions

View File

@@ -14,6 +14,9 @@ set(SOURCES
"src/Texture.cpp" "src/Texture.cpp"
"src/GamePadController.cpp" "src/GamePadController.cpp"
"src/Utils.cpp" "src/Utils.cpp"
"src/BaseEffect.cpp"
"src/FireEffect.cpp"
"src/Material.cpp"
) )
# Create the executable # Create the executable

95
project/resources/Fire.fx Normal file
View File

@@ -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() ) );
}
}

View File

@@ -1,40 +1,49 @@
SamplerState gSampleState : SampleState;
float4x4 gWorldViewProj : WorldViewProjection; float4x4 gWorldViewProj : WorldViewProjection;
float4x4 gWorldMatrix : WorldMatrix;
texture2D gDiffuseMap : DiffuseMap; 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 //Input output
struct VS_INPUT { struct VS_INPUT {
float3 Position : POSITION; 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; float4 Position : SV_POSITION;
float3 Color: COLOR; float4 WorldPosition : WORLDPOSITION;
float2 TexCoord : TEXCOORD; float2 TexCoord : TEXCOORD;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
}; };
//---------------------- //----------------------
// SamplerState // Rasterizer state
//---------------------- //----------------------
SamplerState samPoint RasterizerState gRasterizerState
{ {
Filter = MIN_MAG_MIP_POINT; CullMode = none;
Addressu = Wrap; //or Mirror, Clamp, Border FrontCounterClockwise = false; //default
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
}; };
@@ -43,44 +52,88 @@ VS_OUTPUT VS(VS_INPUT input){
VS_OUTPUT output = (VS_OUTPUT)0; VS_OUTPUT output = (VS_OUTPUT)0;
output.Position = mul(float4(input.Position, 1.f), gWorldViewProj); 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.TexCoord = input.TexCoord;
output.Normal = mul(input.Normal, (float3x3) gWorldMatrix);
output.Tangent = mul(input.Tangent, (float3x3) gWorldMatrix);
return output; return output;
} }
float4 PS_point(VS_OUTPUT input) : SV_TARGET{ float3 Phong(float ks, float exp, float3 l, float3 v, float3 n)
return gDiffuseMap.Sample(samPoint, input.TexCoord); {
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);
} }
float4 PS_anisotropic(VS_OUTPUT input) : SV_TARGET{ // Compute Lambert diffuse lighting
return gDiffuseMap.Sample(samAnisotropic, input.TexCoord); 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;
} }
technique11 PointTechnique{ float4 PS(VS_OUTPUT input) : SV_TARGET{
return float4(Shade(input), 1.f);
}
DepthStencilState gDepthStencilState
{
//enable
DepthEnable = true;
DepthWriteMask = ALL;
DepthFunc = LESS;
//stencil
StencilEnable = true;
};
technique11 DefaultTechnique{
pass P0 { pass P0 {
SetDepthStencilState(gDepthStencilState, 0);
SetVertexShader( CompileShader( vs_5_0, VS() ) ); SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( NULL ); 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() ) );
} }
} }

View File

@@ -0,0 +1,95 @@
#include <fstream>
#include "BaseEffect.h"
#include <iostream>
#include <sstream>
#include <d3dcompiler.h>
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<char *>(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<const float *>(&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() {
}

47
project/src/BaseEffect.h Normal file
View File

@@ -0,0 +1,47 @@
//
// Created by Bram on 20/12/2024.
//
#ifndef GP1_DIRECTX_BASEEFFECT_H
#define GP1_DIRECTX_BASEEFFECT_H
#include <d3d11.h>
#include <d3dx11effect.h>
#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

View File

@@ -188,3 +188,7 @@ void dae::Camera::Update(const dae::Timer *pTimer) {
dae::Matrix dae::Camera::GetViewProjectionMatrix() const { dae::Matrix dae::Camera::GetViewProjectionMatrix() const {
return viewMatrix * ProjectionMatrix; return viewMatrix * ProjectionMatrix;
} }
const dae::Vector3 &dae::Camera::GetPosition() {
return origin;
}

View File

@@ -29,6 +29,8 @@ namespace dae {
Matrix GetViewProjectionMatrix() const; Matrix GetViewProjectionMatrix() const;
const Vector3 &GetPosition();
private: private:
Vector3 origin{}; Vector3 origin{};
float fovAngle{90.f}; float fovAngle{90.f};

View File

@@ -4,100 +4,155 @@
#include <fstream> #include <fstream>
Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath) Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
{ : BaseEffect(devicePtr, filePath) {
const std::ifstream file(filePath);
if(!file)
std::wcout << L"File doesn't exist" << std::endl;
m_EffectPtr = LoadEffect(devicePtr, filePath); m_LightPosVariablePtr = m_EffectPtr->GetVariableByName("gLightDirection")->AsVector();
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("PointTechnique"); if(!m_LightPosVariablePtr->IsValid())
std::wcout << L"gLightDirection Vector is not valid" << std::endl;
if(!m_TechniquePtr->IsValid()) m_SamplerVariablePtr = m_EffectPtr->GetVariableByName("gSampler")->AsSampler();
std::wcout << L"Technique is not valid" << std::endl; if(!m_SamplerVariablePtr->IsValid())
std::wcout << L"gSampler Sampler is not valid" << std::endl;
m_MatWorldViewProjVariablePtr = m_EffectPtr->GetVariableByName("gWorldViewProj")->AsMatrix(); m_MatWorldVariablePtr = m_EffectPtr->GetVariableByName("gWorldMatrix")->AsMatrix();
if(!m_MatWorldViewProjVariablePtr->IsValid()) if(!m_MatWorldVariablePtr->IsValid())
std::wcout << L"gWorldViewProj Matrix is not valid" << std::endl; 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() Effect::~Effect() {
{ m_MatWorldVariablePtr->Release();
m_EffectPtr->Release(); m_MatWorldVariablePtr = nullptr;
m_EffectPtr = nullptr;
// m_TechniquePtr->Release(); m_DiffuseMapVariablePtr->Release();
// m_TechniquePtr = nullptr; m_DiffuseMapVariablePtr = nullptr;
}
ID3DX11Effect* Effect::LoadEffect(ID3D11Device* devicePtr, const std::wstring& filePath) { m_NormalMapVariablePtr->Release();
HRESULT result; m_NormalMapVariablePtr = nullptr;
ID3D10Blob *errorBlobPtr{nullptr};
ID3DX11Effect *effectPtr;
DWORD shaderFlags = 0; m_SpecularMapVariablePtr->Release();
#if defined( DEBUG ) || defined( _DEBUG ) m_SpecularMapVariablePtr = nullptr;
shaderFlags |= D3DCOMPILE_DEBUG;
shaderFlags |= D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
result = D3DX11CompileEffectFromFile(filePath.c_str(), m_GlossMapVariablePtr->Release();
nullptr, m_GlossMapVariablePtr = nullptr;
nullptr,
shaderFlags,
0,
devicePtr,
&effectPtr,
&errorBlobPtr);
if (FAILED(result)) { m_CameraPosVariablePtr->Release();
if (errorBlobPtr != nullptr) { m_CameraPosVariablePtr = nullptr;
const char *errorsPtr = static_cast<char *>(errorBlobPtr->GetBufferPointer());
std::wstringstream ss; m_LightPosVariablePtr->Release();
for (UINT i{}; i < errorBlobPtr->GetBufferSize(); i++) m_LightPosVariablePtr = nullptr;
ss << errorsPtr[i];
OutputDebugStringW(ss.str().c_str()); m_LightColorVariablePtr->Release();
errorBlobPtr->Release(); m_LightColorVariablePtr = nullptr;
errorBlobPtr = nullptr;
return nullptr; m_UseNormalMapVariablePtr->Release();
} else { m_UseNormalMapVariablePtr = nullptr;
std::wstringstream ss;
ss << "EffectLoader: Failed to CreateEffectFromFile!\nPath: " << filePath; m_SamplerVariablePtr->Release();
std::wcout << ss.str() << std::endl; m_SamplerVariablePtr = nullptr;
return nullptr;
for(auto sampler : m_SamplerStates){
sampler->Release();
} }
} }
std::cout << "Effect loaded" << std::endl;
return effectPtr; void Effect::SetWorldMatrix(const dae::Matrix &world) const {
m_MatWorldVariablePtr->SetMatrix(reinterpret_cast<const float*>(&world));
} }
void Effect::SetWorldViewProjMatrix(const dae::Matrix &matrix) { void Effect::SetMaterial(Material* material) {
m_MatWorldViewProjVariablePtr->SetMatrix(reinterpret_cast<const float*>(&matrix)); 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::SetMaterial(const Material &material) {
if(material.diffuseTexturePtr) void Effect::SetCameraPos(const dae::Vector3 &pos) const {
m_EffectPtr->GetVariableByName("gDiffuseMap")->AsShaderResource()->SetResource(material.diffuseTexturePtr->GetSrv()); m_CameraPosVariablePtr->SetFloatVector(reinterpret_cast<const float*>(&pos));
} }
void Effect::NextTechnique() { void Effect::NextSamplingState() {
switch(m_TechniqueType){ switch(m_TechniqueType){
case TechniqueType::Point: case TechniqueType::Point:
m_TechniqueType = TechniqueType::Linear; m_TechniqueType = TechniqueType::Linear;
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("LinearTechnique");
std::cout << "Linear" << std::endl; std::cout << "Linear" << std::endl;
break; break;
case TechniqueType::Linear: case TechniqueType::Linear:
m_TechniqueType = TechniqueType::Anisotropic; m_TechniqueType = TechniqueType::Anisotropic;
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("AnisotropicTechnique");
std::cout << "Anisotropic" << std::endl; std::cout << "Anisotropic" << std::endl;
break; break;
case TechniqueType::Anisotropic: case TechniqueType::Anisotropic:
m_TechniqueType = TechniqueType::Point; m_TechniqueType = TechniqueType::Point;
m_TechniquePtr = m_EffectPtr->GetTechniqueByName("PointTechnique");
std::cout << "Point" << std::endl; std::cout << "Point" << std::endl;
break; break;
} }
m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast<int>(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<int>(TechniqueType::Anisotropic)]);
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast<int>(TechniqueType::Linear)]);
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
devicePtr->CreateSamplerState(&samplerDesc, &m_SamplerStates[static_cast<int>(TechniqueType::Point)]);
m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast<int>(m_TechniqueType)]);
} }

View File

@@ -1,36 +1,53 @@
#pragma once #pragma once
#include "Mesh.h" #include "BaseEffect.h"
#include <array>
enum class TechniqueType { enum class TechniqueType {
Point, Point = 0,
Linear, Linear = 1,
Anisotropic Anisotropic = 2
}; };
class Effect final
{ class Effect: public BaseEffect {
static inline constexpr char TECHNIQUE_NAME[] = "DefaultTechnique";
public: public:
Effect(ID3D11Device *devicePtr, const std::wstring &filePath); Effect(ID3D11Device *devicePtr, const std::wstring &filePath);
~Effect();
inline ID3DX11Effect* GetEffectPtr() const { return m_EffectPtr; } virtual ~Effect() override;
inline ID3DX11EffectTechnique* GetTechniquePtr() const { return m_TechniquePtr; }
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: 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{};
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}; TechniqueType m_TechniqueType{TechniqueType::Linear};
std::array<ID3D11SamplerState*, 3> m_SamplerStates{};
bool m_UseNormalMap{true};
}; };

View File

@@ -0,0 +1,23 @@
//
// Created by Bram on 20/12/2024.
//
#include "FireEffect.h"
#include <iostream>
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());
}

24
project/src/FireEffect.h Normal file
View File

@@ -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

View File

@@ -2,6 +2,7 @@
// Created by Bram on 11/12/2024. // Created by Bram on 11/12/2024.
// //
#include <iostream>
#include "GamePadController.h" #include "GamePadController.h"
GamePadController::GamePadController() = default; GamePadController::GamePadController() = default;
@@ -26,6 +27,44 @@ void GamePadController::Init() {
} }
void GamePadController::Update() { 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++) { for (int i = 0; i < m_pGameControllers.size(); i++) {
SDL_GameController *pController = m_pGameControllers[i]; SDL_GameController *pController = m_pGameControllers[i];
GamePad &gamePad = m_GamePads[i]; GamePad &gamePad = m_GamePads[i];

1
project/src/Material.cpp Normal file
View File

@@ -0,0 +1 @@
#include "Material.h"

22
project/src/Material.h Normal file
View File

@@ -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

View File

@@ -1,26 +1,27 @@
#include <cassert> #include <cassert>
#include <utility>
#include "pch.h" #include "pch.h"
#include "Mesh.h" #include "Mesh.h"
#include "Effect.h" #include "Effect.h"
Mesh::Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices, const Material &material) : Mesh::Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices, std::shared_ptr<Material> material, BaseEffect* effectPtr) :
m_EffectPtr(new Effect{devicePtr, L"resources/PosCol3D.fx"}), m_EffectPtr(effectPtr),
m_InputLayoutPtr(nullptr), m_InputLayoutPtr(nullptr),
m_VertexBufferPtr(nullptr), m_VertexBufferPtr(nullptr),
m_IndexBufferPtr(nullptr), m_IndexBufferPtr(nullptr),
m_VerticesIn(verticesIn), m_VerticesIn(verticesIn),
m_Indices(indices), m_Indices(indices),
m_IndicesCount(static_cast<UINT>(m_Indices.size())), m_IndicesCount(static_cast<UINT>(m_Indices.size())),
m_Material(material) { m_Material(std::move(material)) {
HRESULT result; HRESULT result;
D3D11_BUFFER_DESC bufferDesc{}; D3D11_BUFFER_DESC bufferDesc{};
D3D11_SUBRESOURCE_DATA subresourceData{}; D3D11_SUBRESOURCE_DATA subresourceData{};
m_EffectPtr->SetMaterial(m_Material); m_EffectPtr->SetMaterial(m_Material.get());
//Create vertex layout //Create vertex layout
static constexpr uint32_t vertexElementCount{3}; static constexpr uint32_t vertexElementCount{4};
D3D11_INPUT_ELEMENT_DESC vertexDesc[vertexElementCount]{}; D3D11_INPUT_ELEMENT_DESC vertexDesc[vertexElementCount]{};
vertexDesc[0].SemanticName = "POSITION"; vertexDesc[0].SemanticName = "POSITION";
@@ -28,18 +29,20 @@ Mesh::Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, con
vertexDesc[0].AlignedByteOffset = 0; vertexDesc[0].AlignedByteOffset = 0;
vertexDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; vertexDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
vertexDesc[1].SemanticName = "COLOR"; vertexDesc[1].SemanticName = "TEXCOORD";
vertexDesc[1].Format = DXGI_FORMAT_R32G32B32_FLOAT; vertexDesc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
vertexDesc[1].AlignedByteOffset = offsetof(VertexIn, color); vertexDesc[1].AlignedByteOffset = offsetof(VertexIn, uv);
vertexDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; vertexDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
vertexDesc[2].SemanticName = "TEXCOORD"; vertexDesc[2].SemanticName = "NORMAL";
vertexDesc[2].Format = DXGI_FORMAT_R32G32_FLOAT; vertexDesc[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
vertexDesc[2].AlignedByteOffset = offsetof(VertexIn, uv); vertexDesc[2].AlignedByteOffset = offsetof(VertexIn, normal);
vertexDesc[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; 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 //Create input layout
D3DX11_PASS_DESC passDesc{}; D3DX11_PASS_DESC passDesc{};
@@ -57,7 +60,7 @@ Mesh::Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, con
//Create vertex buffer //Create vertex buffer
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
bufferDesc.ByteWidth = sizeof(verticesIn) * static_cast<uint32_t>(verticesIn.size()); bufferDesc.ByteWidth = sizeof(VertexIn) * static_cast<uint32_t>(verticesIn.size());
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0; bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0; bufferDesc.MiscFlags = 0;
@@ -94,6 +97,7 @@ Mesh::~Mesh() {
void Mesh::Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldViewProj) const { void Mesh::Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldViewProj) const {
m_EffectPtr->SetWorldViewProjMatrix(worldViewProj); m_EffectPtr->SetWorldViewProjMatrix(worldViewProj);
m_EffectPtr->SetWorldMatrix(m_WorldMatrix);
//1. Set primitive topology //1. Set primitive topology
deviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); deviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
@@ -117,6 +121,18 @@ void Mesh::Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldView
} }
} }
void Mesh::NextTechnique() { void Mesh::NextSamplingState() {
m_EffectPtr->NextTechnique(); 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();
} }

View File

@@ -1,36 +1,44 @@
#pragma once #pragma once
#include "Texture.h" #include "Texture.h"
#include "BaseEffect.h"
#include <d3d11.h>
#include <vector>
class Effect; class Effect;
using namespace dae; using namespace dae;
struct VertexIn; struct VertexIn;
struct VertexOut; struct VertexOut;
struct Material{
Texture* diffuseTexturePtr{ nullptr };
~Material(){
if(diffuseTexturePtr){
delete diffuseTexturePtr;
}
}
};
class Mesh final class Mesh final {
{
public: public:
Mesh(ID3D11Device* devicePtr, const std::vector<VertexIn>& verticesIn, const std::vector<Uint32>& indices, const Material& material); Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices,
std::shared_ptr<Material> material, BaseEffect* effectPtr);
~Mesh(); ~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: private:
Effect* m_EffectPtr; BaseEffect *m_EffectPtr;
Matrix m_WorldMatrix{};
ID3D11InputLayout *m_InputLayoutPtr; ID3D11InputLayout *m_InputLayoutPtr;
ID3D11Buffer *m_VertexBufferPtr; ID3D11Buffer *m_VertexBufferPtr;
@@ -40,24 +48,22 @@ private:
std::vector<uint32_t> m_Indices; std::vector<uint32_t> m_Indices;
UINT m_IndicesCount; UINT m_IndicesCount;
Material m_Material{}; std::shared_ptr<Material> m_Material{};
}; };
struct VertexIn struct VertexIn {
{
Vector3 position{}; Vector3 position{};
Vector3 color{};
Vector2 uv{}; Vector2 uv{};
// Vector3 normal{}; Vector3 normal{};
// Vector3 tangent{}; Vector3 tangent{};
}; };
struct VertexOut struct VertexOut {
{
Vector4 position{}; Vector4 position{};
Vector3 color{}; ColorRGB color{};
Vector2 uv{}; Vector2 uv{};
// Vector3 normal{}; Vector3 normal{};
Vector3 tangent{};
Vector3 viewDir{};
}; };

View File

@@ -2,6 +2,9 @@
#include "Renderer.h" #include "Renderer.h"
#include "Mesh.h" #include "Mesh.h"
#include "Utils.h" #include "Utils.h"
#include "Texture.h"
#include "Effect.h"
#include "FireEffect.h"
namespace dae { namespace dae {
@@ -18,11 +21,15 @@ namespace dae {
} else { } else {
std::cout << "DirectX initialization failed!\n"; std::cout << "DirectX initialization failed!\n";
} }
InitializeSDLRasterizer();
std::vector<VertexIn> vertices{}; std::vector<VertexIn> vertices{};
std::vector<uint32_t> indices{}; std::vector<uint32_t> 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; std::cout << "Model Loaded" << std::endl;
} else { } else {
std::cout << "Model failed to load" << std::endl; std::cout << "Model failed to load" << std::endl;
assert(true && "Model failed to load"); assert(true && "Model failed to load");
@@ -30,11 +37,36 @@ namespace dae {
std::cout << "Vertices: " << vertices.size() << " Indices: " << indices.size() << std::endl; std::cout << "Vertices: " << vertices.size() << " Indices: " << indices.size() << std::endl;
m_material.diffuseTexturePtr = Texture::LoadFromFile("resources/uv_grid_2.png", m_DevicePtr); std::shared_ptr<Material> vehicleMaterial = std::make_shared<Material>();
m_mesh = new Mesh(m_DevicePtr, vertices, indices, m_material); 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); Effect* effect = new Effect(m_DevicePtr, L"resources/PosCol3D.fx");
m_Camera.Initialize(90.f, Vector3(0.f, 0.f, -5.f), 1.f); 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<Material> FireMaterial = std::make_shared<Material>();
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<float>(m_Width) / static_cast<float>(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() { Renderer::~Renderer() {
@@ -54,34 +86,61 @@ namespace dae {
m_DevicePtr->Release(); m_DevicePtr->Release();
delete m_mesh; for (auto mesh: m_meshes) {
delete mesh;
}
} }
void Renderer::Update(const Timer *pTimer) { void Renderer::Update(const Timer *pTimer) {
m_Camera.Update(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 { void Renderer::Render() const {
if (!m_IsInitialized) if (!m_IsInitialized)
return; return;
if (m_backendType == Backendtype::DirectX) {
//Clear back buffer //Clear back buffer
const float clearColor[] = {.39f, .59f, .93f, 1.f}; 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->ClearRenderTargetView(m_RenderTargetViewPtr, clearColor);
m_DeviceContextPtr->ClearDepthStencilView(m_DepthStencilViewPtr, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); m_DeviceContextPtr->ClearDepthStencilView(m_DepthStencilViewPtr, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
Matrix worldViewProj = m_Camera.GetViewProjectionMatrix(); Matrix viewProjMatrix = m_Camera.GetViewProjectionMatrix();
Matrix modelMatrix{}; 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 //Present
m_SwapChainPtr->Present(0, 0); m_SwapChainPtr->Present(0, 0);
} else {
SDL_FillRect(m_pBackBuffer, nullptr, Uint32(255 << 24) + Uint32(100 << 16) + Uint32(100 << 8) + Uint32(100));
//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; 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;
} }
} }

View File

@@ -6,6 +6,11 @@
struct SDL_Window; struct SDL_Window;
struct SDL_Surface; struct SDL_Surface;
enum class Backendtype {
DirectX,
SDL
};
namespace dae namespace dae
{ {
class Renderer final class Renderer final
@@ -23,7 +28,14 @@ namespace dae
void Render() const; void Render() const;
//Switching Functions //Switching Functions
void SwitchTechnique(); void NextSamplingState();
void ToggleNormals();
void SwitchBackend();
void ToggleRotation();
void ToggleUniformClearColor();
private: private:
SDL_Window* m_pWindow{}; SDL_Window* m_pWindow{};
@@ -35,6 +47,7 @@ namespace dae
//DIRECTX //DIRECTX
HRESULT InitializeDirectX(); HRESULT InitializeDirectX();
void InitializeSDLRasterizer();
ID3D11Device* m_DevicePtr{}; ID3D11Device* m_DevicePtr{};
ID3D11DeviceContext* m_DeviceContextPtr{}; ID3D11DeviceContext* m_DeviceContextPtr{};
@@ -44,11 +57,21 @@ namespace dae
ID3D11Resource* m_RenderTargetBufferPtr{}; ID3D11Resource* m_RenderTargetBufferPtr{};
ID3D11RenderTargetView* m_RenderTargetViewPtr{}; 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<Mesh*> m_meshes{};
std::vector<std::shared_ptr<Material>> m_materials{};
Backendtype m_backendType{ Backendtype::DirectX };
Camera m_Camera{}; Camera m_Camera{};
bool m_Rotating{ false };
float m_currentRotation{};
bool m_UniformClearColor{ false };
}; };
} }

View File

@@ -12,7 +12,7 @@ Texture *Texture::LoadFromFile(const std::string &path, ID3D11Device *devicePtr)
return nullptr; return nullptr;
} }
Texture *texture = new Texture(surface, devicePtr); auto *texture = new Texture(surface, devicePtr);
return texture; return texture;
} }

View File

@@ -103,42 +103,42 @@ namespace dae {
file.ignore(1000, '\n'); file.ignore(1000, '\n');
} }
// //Cheap Tangent Calculations //Cheap Tangent Calculations
// for (uint32_t i = 0; i < indices.size(); i += 3) { for (uint32_t i = 0; i < indices.size(); i += 3) {
// uint32_t index0 = indices[i]; uint32_t index0 = indices[i];
// uint32_t index1 = indices[size_t(i) + 1]; uint32_t index1 = indices[size_t(i) + 1];
// uint32_t index2 = indices[size_t(i) + 2]; uint32_t index2 = indices[size_t(i) + 2];
//
// const Vector3 &p0 = vertices[index0].position; const Vector3 &p0 = vertices[index0].position;
// const Vector3 &p1 = vertices[index1].position; const Vector3 &p1 = vertices[index1].position;
// const Vector3 &p2 = vertices[index2].position; const Vector3 &p2 = vertices[index2].position;
// const Vector2 &uv0 = vertices[index0].uv; const Vector2 &uv0 = vertices[index0].uv;
// const Vector2 &uv1 = vertices[index1].uv; const Vector2 &uv1 = vertices[index1].uv;
// const Vector2 &uv2 = vertices[index2].uv; const Vector2 &uv2 = vertices[index2].uv;
//
// const Vector3 edge0 = p1 - p0; const Vector3 edge0 = p1 - p0;
// const Vector3 edge1 = p2 - p0; const Vector3 edge1 = p2 - p0;
// const Vector2 diffX = Vector2(uv1.x - uv0.x, uv2.x - uv0.x); const Vector2 diffX = Vector2(uv1.x - uv0.x, uv2.x - uv0.x);
// const Vector2 diffY = Vector2(uv1.y - uv0.y, uv2.y - uv0.y); const Vector2 diffY = Vector2(uv1.y - uv0.y, uv2.y - uv0.y);
// float r = 1.f / Vector2::Cross(diffX, diffY); float r = 1.f / Vector2::Cross(diffX, diffY);
//
// Vector3 tangent = (edge0 * diffY.y - edge1 * diffY.x) * r; Vector3 tangent = (edge0 * diffY.y - edge1 * diffY.x) * r;
// vertices[index0].tangent += tangent; vertices[index0].tangent += tangent;
// vertices[index1].tangent += tangent; vertices[index1].tangent += tangent;
// vertices[index2].tangent += tangent; vertices[index2].tangent += tangent;
// } }
//
// //Fix the tangents per vertex now because we accumulated //Fix the tangents per vertex now because we accumulated
// for (auto &v: vertices) { for (auto &v: vertices) {
// v.tangent = Vector3::Reject(v.tangent, v.normal).Normalized(); v.tangent = Vector3::Reject(v.tangent, v.normal).Normalized();
//
// if (flipAxisAndWinding) { if (flipAxisAndWinding) {
// v.position.z *= -1.f; v.position.z *= -1.f;
// v.normal.z *= -1.f; v.normal.z *= -1.f;
// v.tangent.z *= -1.f; v.tangent.z *= -1.f;
// } }
//
// } }
return true; return true;
} }
@@ -169,7 +169,7 @@ namespace dae {
size_t index_offset = 0; size_t index_offset = 0;
for (size_t f = 0; f < shape.mesh.num_face_vertices.size(); f++) { 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) { if (fv != 3) {
std::cerr << "Error: Only triangular faces are supported." << std::endl; std::cerr << "Error: Only triangular faces are supported." << std::endl;
@@ -177,6 +177,7 @@ namespace dae {
} }
uint32_t tempIndices[3]; uint32_t tempIndices[3];
VertexIn tempVertices[3];
for (size_t v = 0; v < fv; v++) { for (size_t v = 0; v < fv; v++) {
tinyobj::index_t idx = shape.mesh.indices[index_offset + v]; tinyobj::index_t idx = shape.mesh.indices[index_offset + v];
@@ -202,16 +203,17 @@ namespace dae {
} }
if (idx.normal_index >= 0) { if (idx.normal_index >= 0) {
// vertex.normal = Vector3( vertex.normal = Vector3(
// attrib.normals[3 * idx.normal_index + 0], attrib.normals[3 * idx.normal_index + 0],
// attrib.normals[3 * idx.normal_index + 1], attrib.normals[3 * idx.normal_index + 1],
// attrib.normals[3 * idx.normal_index + 2] attrib.normals[3 * idx.normal_index + 2]
// ); );
// if (flipAxisAndWinding) { if (flipAxisAndWinding) {
// vertex.normal.z *= -1.0f; vertex.normal.z *= -1.0f;
// } }
} }
tempVertices[v] = vertex;
vertices.push_back(vertex); vertices.push_back(vertex);
tempIndices[v] = static_cast<uint32_t>(vertices.size() - 1); tempIndices[v] = static_cast<uint32_t>(vertices.size() - 1);
} }
@@ -225,10 +227,30 @@ namespace dae {
indices.push_back(tempIndices[2]); 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; index_offset += fv;
shape.mesh.material_ids[f];
} }
} }

View File

@@ -42,16 +42,6 @@ int main(int argc, char *args[]) {
int joysticks = SDL_NumJoysticks(); int joysticks = SDL_NumJoysticks();
std::cout << "Number of joysticks connected: " << joysticks << std::endl; 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(); GamePadController::GetInstance().Init();
@@ -71,14 +61,59 @@ int main(int argc, char *args[]) {
case SDL_QUIT: case SDL_QUIT:
isLooping = false; isLooping = false;
break; break;
case SDL_KEYUP: case SDL_KEYUP: {
//Test for a key SDL_Scancode scancode = e.key.keysym.scancode;
//if (e.key.keysym.scancode == SDL_SCANCODE_X) 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) { 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; break;
}
default: default:
break; break;
} }