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/GamePadController.cpp"
"src/Utils.cpp"
"src/BaseEffect.cpp"
"src/FireEffect.cpp"
"src/Material.cpp"
)
# 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 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() ) );
}
}
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() ) );
SetPixelShader( CompileShader( ps_5_0, PS() ) );
}
}

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 {
return viewMatrix * ProjectionMatrix;
}
const dae::Vector3 &dae::Camera::GetPosition() {
return origin;
}

View File

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

View File

@@ -3,101 +3,156 @@
#include <fstream>
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<char *>(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<const float*>(&matrix));
void Effect::SetWorldMatrix(const dae::Matrix &world) const {
m_MatWorldVariablePtr->SetMatrix(reinterpret_cast<const float*>(&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<const float*>(&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<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
#include "Mesh.h"
#include "BaseEffect.h"
#include <array>
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<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.
//
#include <iostream>
#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];

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 <utility>
#include "pch.h"
#include "Mesh.h"
#include "Effect.h"
Mesh::Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices, const Material &material) :
m_EffectPtr(new Effect{devicePtr, L"resources/PosCol3D.fx"}),
Mesh::Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices, std::shared_ptr<Material> 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<UINT>(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<VertexIn> &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<VertexIn> &verticesIn, con
//Create vertex buffer
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.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();
}

View File

@@ -1,63 +1,69 @@
#pragma once
#include "Texture.h"
#include "BaseEffect.h"
#include <d3d11.h>
#include <vector>
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<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();
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<VertexIn> m_VerticesIn;
std::vector<uint32_t> m_Indices;
UINT m_IndicesCount;
Material m_Material{};
std::shared_ptr<Material> 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{};
};

View File

@@ -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<VertexIn> vertices{};
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;
} 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<Material> vehicleMaterial = std::make_shared<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);
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<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() {
@@ -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};
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;
//Render
m_mesh->Render(m_DeviceContextPtr, worldViewProj * modelMatrix);
mesh->Render(m_DeviceContextPtr, worldViewProjMatrix);
}
//Present
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;
}
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_Surface;
enum class Backendtype {
DirectX,
SDL
};
namespace dae
{
class Renderer final
@@ -23,7 +28,14 @@ namespace dae
void Render() const;
//Switching Functions
void SwitchTechnique();
void NextSamplingState();
void ToggleNormals();
void SwitchBackend();
void ToggleRotation();
void ToggleUniformClearColor();
private:
SDL_Window* m_pWindow{};
@@ -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<Mesh*> m_meshes{};
std::vector<std::shared_ptr<Material>> m_materials{};
Backendtype m_backendType{ Backendtype::DirectX };
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;
}
Texture *texture = new Texture(surface, devicePtr);
auto *texture = new Texture(surface, devicePtr);
return texture;
}

View File

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

View File

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