Boom exam done!
@@ -9,6 +9,7 @@ set(SOURCES
|
||||
"src/Texture.cpp"
|
||||
"src/GamePadController.cpp"
|
||||
"src/Utils.cpp"
|
||||
"src/HitTest.cpp"
|
||||
"src/Material.cpp"
|
||||
"src/Math/Vector2.cpp"
|
||||
"src/Math/Vector3.cpp"
|
||||
@@ -50,6 +51,7 @@ file(GLOB_RECURSE RESOURCE_FILES
|
||||
"${RESOURCES_SOURCE_DIR}/*.png"
|
||||
"${RESOURCES_SOURCE_DIR}/*.obj"
|
||||
"${RESOURCES_SOURCE_DIR}/*.fx"
|
||||
"${RESOURCES_SOURCE_DIR}/*.mtl"
|
||||
)
|
||||
set(RESOURCES_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/resources/")
|
||||
file(MAKE_DIRECTORY ${RESOURCES_OUT_DIR})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
SamplerState gSampleState : SampleState;
|
||||
RasterizerState gRasterizerState : RasState;
|
||||
|
||||
float4x4 gWorldViewProj : WorldViewProjection;
|
||||
float4x4 gWorldMatrix : WorldMatrix;
|
||||
@@ -39,12 +40,12 @@ struct VS_OUTPUT {
|
||||
|
||||
//----------------------
|
||||
// Rasterizer state
|
||||
//----------------------
|
||||
RasterizerState gRasterizerState
|
||||
{
|
||||
CullMode = none;
|
||||
FrontCounterClockwise = false; //default
|
||||
};
|
||||
// //----------------------
|
||||
// RasterizerState gRasterizerState
|
||||
// {
|
||||
// CullMode = none;
|
||||
// FrontCounterClockwise = false; //default
|
||||
// };
|
||||
|
||||
|
||||
//Vertex shader
|
||||
|
||||
141
project/resources/SimpleDiffuse.fx
Normal file
@@ -0,0 +1,141 @@
|
||||
SamplerState gSampleState : SampleState;
|
||||
RasterizerState gRasterizerState : RastState;
|
||||
|
||||
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 {
|
||||
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
|
||||
// };
|
||||
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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(VS_OUTPUT input) : SV_TARGET{
|
||||
return gDiffuseMap.Sample(gSampleState, input.TexCoord);
|
||||
}
|
||||
|
||||
DepthStencilState gDepthStencilState
|
||||
{
|
||||
//enable
|
||||
DepthEnable = true;
|
||||
DepthWriteMask = ALL;
|
||||
DepthFunc = LESS;
|
||||
//stencil
|
||||
StencilEnable = true;
|
||||
};
|
||||
|
||||
|
||||
technique11 DefaultTechnique{
|
||||
pass P0 {
|
||||
SetDepthStencilState(gDepthStencilState, 0);
|
||||
SetRasterizerState(gRasterizerState);
|
||||
SetVertexShader( CompileShader( vs_5_0, VS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_5_0, PS() ) );
|
||||
}
|
||||
}
|
||||
BIN
project/resources/T_BrickWall_C.png
Normal file
|
After Width: | Height: | Size: 635 KiB |
BIN
project/resources/T_Brick_C.png
Normal file
|
After Width: | Height: | Size: 663 KiB |
BIN
project/resources/T_Car_C.png
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
project/resources/T_ChainBench_C.png
Normal file
|
After Width: | Height: | Size: 290 KiB |
BIN
project/resources/T_ChainBench_O.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
project/resources/T_ChickenCoopRoof_C.png
Normal file
|
After Width: | Height: | Size: 488 KiB |
BIN
project/resources/T_ChickenWireInside_C.png
Normal file
|
After Width: | Height: | Size: 274 KiB |
BIN
project/resources/T_ChickenWire_C.png
Normal file
|
After Width: | Height: | Size: 278 KiB |
BIN
project/resources/T_ChickenWire_O.png
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
project/resources/T_Chicken_C.png
Normal file
|
After Width: | Height: | Size: 229 KiB |
BIN
project/resources/T_Chicken_O.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
project/resources/T_ClothesLine_C.png
Normal file
|
After Width: | Height: | Size: 305 KiB |
BIN
project/resources/T_DirtTrim_C.png
Normal file
|
After Width: | Height: | Size: 551 KiB |
BIN
project/resources/T_Dirt_C.png
Normal file
|
After Width: | Height: | Size: 378 KiB |
BIN
project/resources/T_Flowers_C.png
Normal file
|
After Width: | Height: | Size: 982 KiB |
BIN
project/resources/T_Flowers_wheel_O.png
Normal file
|
After Width: | Height: | Size: 759 KiB |
BIN
project/resources/T_Fountain_C.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
project/resources/T_GardenFlowers_Grass_C.png
Normal file
|
After Width: | Height: | Size: 340 KiB |
BIN
project/resources/T_GardenFlowers_Grass_O.png
Normal file
|
After Width: | Height: | Size: 368 KiB |
BIN
project/resources/T_GlassPane_C.png
Normal file
|
After Width: | Height: | Size: 332 KiB |
BIN
project/resources/T_GroundGrass_C.png
Normal file
|
After Width: | Height: | Size: 645 KiB |
BIN
project/resources/T_Hay_C.png
Normal file
|
After Width: | Height: | Size: 793 KiB |
BIN
project/resources/T_HouseTrim_C.png
Normal file
|
After Width: | Height: | Size: 421 KiB |
BIN
project/resources/T_HouseUnique_C.png
Normal file
|
After Width: | Height: | Size: 440 KiB |
BIN
project/resources/T_Leaf_C.png
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
project/resources/T_Leaf_O.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
project/resources/T_LocustBark_C.png
Normal file
|
After Width: | Height: | Size: 280 KiB |
BIN
project/resources/T_Path_C.png
Normal file
|
After Width: | Height: | Size: 610 KiB |
BIN
project/resources/T_Rocks_Wall_C.png
Normal file
|
After Width: | Height: | Size: 409 KiB |
BIN
project/resources/T_Roof_C.png
Normal file
|
After Width: | Height: | Size: 502 KiB |
BIN
project/resources/T_Sand_C.png
Normal file
|
After Width: | Height: | Size: 431 KiB |
BIN
project/resources/T_SingleBrick_C.png
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
project/resources/T_TableCloth_C.png
Normal file
|
After Width: | Height: | Size: 672 KiB |
BIN
project/resources/T_TableUnique_c.png
Normal file
|
After Width: | Height: | Size: 456 KiB |
BIN
project/resources/T_Vase_C.png
Normal file
|
After Width: | Height: | Size: 329 KiB |
BIN
project/resources/T_Vines_C.png
Normal file
|
After Width: | Height: | Size: 383 KiB |
BIN
project/resources/T_Vines_O.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
project/resources/T_Water_C.png
Normal file
|
After Width: | Height: | Size: 326 KiB |
BIN
project/resources/T_WoodSeamless_C.png
Normal file
|
After Width: | Height: | Size: 395 KiB |
BIN
project/resources/T_WorldTrimm_C.png
Normal file
|
After Width: | Height: | Size: 243 KiB |
39
project/resources/converter.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from PIL import Image
|
||||
import os
|
||||
import pprint
|
||||
|
||||
# Set the folder containing images
|
||||
folder_path = 'converted' # Replace with your folder path
|
||||
output_folder = os.path.join(folder_path, 'dingus')
|
||||
|
||||
# Create the 'dingus' folder if it doesn't exist
|
||||
if not os.path.exists(output_folder):
|
||||
os.makedirs(output_folder)
|
||||
|
||||
# Initialize a pretty printer
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
|
||||
# Iterate through all files in the folder
|
||||
for filename in os.listdir(folder_path):
|
||||
if filename.endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tiff')): # Add more formats if needed
|
||||
file_path = os.path.join(folder_path, filename)
|
||||
|
||||
# Open the image
|
||||
try:
|
||||
with Image.open(file_path) as img:
|
||||
# Ensure the image is in 'RGBA' mode (32-bit with 4 channels: R, G, B, A)
|
||||
img = img.convert('RGBA')
|
||||
|
||||
# Create the save path as a PNG in the 'dingus' folder
|
||||
save_path = os.path.join(output_folder, f'{os.path.splitext(filename)[0]}.png')
|
||||
|
||||
# Save the image as PNG
|
||||
img.save(save_path, 'PNG')
|
||||
|
||||
# Pretty-print the successful conversion
|
||||
pp.pprint(f"Successfully converted and saved: {save_path}")
|
||||
|
||||
except Exception as e:
|
||||
pp.pprint(f"Error processing {filename}: {e}")
|
||||
|
||||
print("Conversion complete!")
|
||||
352
project/resources/scene.mtl
Normal file
@@ -0,0 +1,352 @@
|
||||
# Blender 4.3.2 MTL File: '1GD16E_Verhulst_Bram_Diorama.blend'
|
||||
# www.blender.org
|
||||
|
||||
newmtl M_Baksteen
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_SingleBrick_C.png
|
||||
|
||||
newmtl M_Brick
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Brick_C.png
|
||||
|
||||
newmtl M_Car
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Car_C.png
|
||||
|
||||
newmtl M_Chicken
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_Chicken_C.png
|
||||
map_d T_Chicken_O.png
|
||||
|
||||
newmtl M_ChickenRoof
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_ChickenCoopRoof_C.png
|
||||
|
||||
newmtl M_ChickenWireFence
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_ChickenWire_C.png
|
||||
map_d T_ChickenWire_O.png
|
||||
|
||||
newmtl M_Cliff
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_BrickWall_C.png
|
||||
|
||||
newmtl M_ClothesLine
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_ClothesLine_C.png
|
||||
|
||||
newmtl M_Dirt
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Dirt_C.png
|
||||
|
||||
newmtl M_DirtTrimm
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_DirtTrim_C.png
|
||||
|
||||
newmtl M_Fountain
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Fountain_C.png
|
||||
|
||||
newmtl M_GardenFlowers
|
||||
Ns 200.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_GardenFlowers_Grass_C.png
|
||||
map_d T_GardenFlowers_Grass_O.png
|
||||
|
||||
newmtl M_GlassPane
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.376859
|
||||
illum 1
|
||||
map_Kd T_GlassPane_C.png
|
||||
|
||||
newmtl M_Grass
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_GroundGrass_C.png
|
||||
|
||||
newmtl M_GrassFlowers
|
||||
Ns 1000.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_Flowers_C.png
|
||||
map_d T_Flowers_wheel_O.png
|
||||
|
||||
newmtl M_Hay
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Hay_C.png
|
||||
|
||||
newmtl M_HouseTrim
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_HouseTrim_C.png
|
||||
|
||||
newmtl M_HouseUnique
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_HouseUnique_C.png
|
||||
|
||||
newmtl M_IndoorChickenWire
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_ChickenWireInside_C.png
|
||||
|
||||
newmtl M_LawnMower_Ladder_pots
|
||||
Ns 200.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
|
||||
newmtl M_Path
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Path_C.png
|
||||
|
||||
newmtl M_PlantPot
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Vase_C.png
|
||||
|
||||
newmtl M_Plants
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_Flowers_C.png
|
||||
map_d T_Flowers_wheel_O.png
|
||||
|
||||
newmtl M_Rocks_Wall
|
||||
Ns 200.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Rocks_Wall_C.png
|
||||
|
||||
newmtl M_RoofTiles
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Roof_C.png
|
||||
|
||||
newmtl M_Sand
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_Sand_C.png
|
||||
|
||||
newmtl M_SwingChair
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_ChainBench_C.png
|
||||
map_d T_ChainBench_O.png
|
||||
|
||||
newmtl M_TableCloth
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_TableCloth_C.png
|
||||
|
||||
newmtl M_TableUnique
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_TableUnique_c.png
|
||||
|
||||
newmtl M_TreeBark
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_LocustBark_C.png
|
||||
|
||||
newmtl M_TreeLeaf
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_Leaf_C.png
|
||||
map_d T_Leaf_O.png
|
||||
|
||||
newmtl M_Vines
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
illum 1
|
||||
map_Kd T_Vines_C.png
|
||||
map_d T_Vines_O.png
|
||||
|
||||
newmtl M_Water
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.269091
|
||||
illum 1
|
||||
map_Kd T_Water_C.png
|
||||
|
||||
newmtl M_WoodPlanks
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_WoodSeamless_C.png
|
||||
|
||||
newmtl M_WorldTrimm
|
||||
Ns 250.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Ks 0.000000 0.000000 0.000000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 1
|
||||
map_Kd T_WorldTrimm_C.png
|
||||
@@ -163,7 +163,7 @@ void dae::Camera::Update(const dae::Timer *pTimer) {
|
||||
mousePosChange = true;
|
||||
} else if (mouseState == SDL_BUTTON_X2) //lmb + rmb
|
||||
{
|
||||
origin.y += static_cast<float>(mouseY) / 2;
|
||||
origin.y -= static_cast<float>(mouseY) / 2;
|
||||
|
||||
mousePosChange = true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "Math/MathHelpers.h"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace dae
|
||||
{
|
||||
@@ -11,7 +13,7 @@ namespace dae
|
||||
|
||||
void MaxToOne()
|
||||
{
|
||||
const float maxValue = std::max(r, std::max(g, b));
|
||||
const float maxValue = (r > g) ? ((r > b) ? r : b) : ((g > b) ? g : b);
|
||||
if (maxValue > 1.f)
|
||||
*this /= maxValue;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ ID3DX11Effect *BaseEffect::LoadEffect(ID3D11Device *devicePtr, const std::wstrin
|
||||
std::wstringstream ss;
|
||||
for (UINT i{}; i < errorBlobPtr->GetBufferSize(); i++)
|
||||
ss << errorsPtr[i];
|
||||
|
||||
OutputDebugStringW(ss.str().c_str());
|
||||
|
||||
errorBlobPtr->Release();
|
||||
@@ -66,7 +65,6 @@ ID3DX11Effect *BaseEffect::LoadEffect(ID3D11Device *devicePtr, const std::wstrin
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
std::cout << "Effect loaded" << std::endl;
|
||||
return effectPtr;
|
||||
}
|
||||
|
||||
@@ -93,3 +91,7 @@ void BaseEffect::SetWorldMatrix(const dae::Matrix& matrix) const {
|
||||
void BaseEffect::ToggleNormals() {
|
||||
|
||||
}
|
||||
|
||||
void BaseEffect::NextCullMode() {
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ public:
|
||||
|
||||
virtual void NextSamplingState();
|
||||
|
||||
virtual void NextCullMode();
|
||||
|
||||
virtual void SetCameraPos(const dae::Vector3 &vector3) const;
|
||||
|
||||
virtual void SetMaterial(Material *material);
|
||||
|
||||
@@ -10,9 +10,9 @@ Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
|
||||
if(!m_LightPosVariablePtr->IsValid())
|
||||
std::wcout << L"gLightDirection Vector is not valid" << std::endl;
|
||||
|
||||
m_SamplerVariablePtr = m_EffectPtr->GetVariableByName("gSampler")->AsSampler();
|
||||
m_SamplerVariablePtr = m_EffectPtr->GetVariableByName("gSampleState")->AsSampler();
|
||||
if(!m_SamplerVariablePtr->IsValid())
|
||||
std::wcout << L"gSampler Sampler is not valid" << std::endl;
|
||||
std::wcout << L"gSampleState Sampler is not valid" << std::endl;
|
||||
|
||||
m_MatWorldVariablePtr = m_EffectPtr->GetVariableByName("gWorldMatrix")->AsMatrix();
|
||||
if(!m_MatWorldVariablePtr->IsValid())
|
||||
@@ -46,9 +46,15 @@ Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
|
||||
if(!m_UseNormalMapVariablePtr->IsValid())
|
||||
std::wcout << L"gUseNormalMap Scalar is not valid" << std::endl;
|
||||
|
||||
m_RasterizerVariablePtr = m_EffectPtr->GetVariableByName("gRasterizerState")->AsRasterizer();
|
||||
if(!m_RasterizerVariablePtr->IsValid())
|
||||
std::wcout << L"gRasterizerState Rasterizer 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);
|
||||
@@ -57,6 +63,10 @@ Effect::Effect(ID3D11Device *devicePtr, const std::wstring &filePath)
|
||||
m_LightColorVariablePtr->SetFloatVector(lightColor);
|
||||
|
||||
this->InitSamplers(devicePtr);
|
||||
this->InitRasterizer(devicePtr);
|
||||
|
||||
m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast<int>(m_TechniqueType)]);
|
||||
m_RasterizerVariablePtr->SetRasterizerState(0,m_RasterizerStates[static_cast<int>(m_CullMode)]);
|
||||
}
|
||||
|
||||
Effect::~Effect() {
|
||||
@@ -90,6 +100,9 @@ Effect::~Effect() {
|
||||
m_SamplerVariablePtr->Release();
|
||||
m_SamplerVariablePtr = nullptr;
|
||||
|
||||
m_RasterizerVariablePtr->Release();
|
||||
m_RasterizerVariablePtr = nullptr;
|
||||
|
||||
for(auto sampler : m_SamplerStates){
|
||||
sampler->Release();
|
||||
}
|
||||
@@ -156,3 +169,32 @@ void Effect::InitSamplers(ID3D11Device *devicePtr) {
|
||||
|
||||
m_SamplerVariablePtr->SetSampler(0,m_SamplerStates[static_cast<int>(m_TechniqueType)]);
|
||||
}
|
||||
|
||||
void Effect::NextCullMode() {
|
||||
m_CullMode = static_cast<CullMode>((static_cast<int>(m_CullMode) + 1) % 3);
|
||||
m_RasterizerVariablePtr->SetRasterizerState(0,m_RasterizerStates[static_cast<int>(m_CullMode)]);
|
||||
}
|
||||
|
||||
void Effect::InitRasterizer(ID3D11Device *devicePtr) {
|
||||
D3D11_RASTERIZER_DESC rasterDesc = {};
|
||||
rasterDesc.FillMode = D3D11_FILL_SOLID; // Solid fill
|
||||
rasterDesc.FrontCounterClockwise = FALSE;
|
||||
rasterDesc.DepthBias = D3D11_DEFAULT_DEPTH_BIAS;
|
||||
rasterDesc.SlopeScaledDepthBias = D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
||||
rasterDesc.DepthClipEnable = TRUE;
|
||||
rasterDesc.ScissorEnable = FALSE;
|
||||
rasterDesc.MultisampleEnable = FALSE;
|
||||
rasterDesc.AntialiasedLineEnable = FALSE;
|
||||
|
||||
rasterDesc.CullMode = D3D11_CULL_BACK; // Cull back faces
|
||||
|
||||
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::Back)]);
|
||||
|
||||
rasterDesc.CullMode = D3D11_CULL_FRONT;
|
||||
|
||||
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::Front)]);
|
||||
|
||||
rasterDesc.CullMode = D3D11_CULL_NONE;
|
||||
|
||||
devicePtr->CreateRasterizerState(&rasterDesc, &m_RasterizerStates[static_cast<int>(CullMode::None)]);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,12 @@ enum class TechniqueType {
|
||||
Anisotropic = 2
|
||||
};
|
||||
|
||||
enum class CullMode {
|
||||
None = 0,
|
||||
Front = 1,
|
||||
Back = 2
|
||||
};
|
||||
|
||||
|
||||
class Effect: public BaseEffect {
|
||||
public:
|
||||
@@ -20,15 +26,18 @@ public:
|
||||
|
||||
void SetCameraPos(const dae::Vector3 &pos) const override;
|
||||
|
||||
void SetMaterial(Material *material);
|
||||
void SetMaterial(Material *material) override;
|
||||
|
||||
void ToggleNormals() override;
|
||||
|
||||
void NextSamplingState() override;
|
||||
|
||||
void NextCullMode() override;
|
||||
|
||||
private:
|
||||
|
||||
void InitSamplers(ID3D11Device* devicePtr);
|
||||
void InitRasterizer(ID3D11Device* devicePtr);
|
||||
|
||||
ID3DX11EffectMatrixVariable *m_MatWorldVariablePtr{};
|
||||
|
||||
@@ -45,9 +54,14 @@ private:
|
||||
|
||||
ID3DX11EffectSamplerVariable *m_SamplerVariablePtr{};
|
||||
|
||||
ID3DX11EffectRasterizerVariable* m_RasterizerVariablePtr{};
|
||||
|
||||
TechniqueType m_TechniqueType{TechniqueType::Linear};
|
||||
|
||||
std::array<ID3D11SamplerState*, 3> m_SamplerStates{};
|
||||
std::array<ID3D11RasterizerState*, 3> m_RasterizerStates{};
|
||||
|
||||
CullMode m_CullMode{ CullMode::Back };
|
||||
|
||||
bool m_UseNormalMap{true};
|
||||
};
|
||||
|
||||
72
project/src/HitTest.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "HitTest.h"
|
||||
|
||||
|
||||
|
||||
float CrossZ(const Vector3& p0, const Vector3& p1, const Vector3& point)
|
||||
{
|
||||
return (p1.x - p0.x) * (point.y - p0.y)
|
||||
- (p1.y - p0.y) * (point.x - p0.x);
|
||||
}
|
||||
|
||||
std::optional<Sample> TriangleHitTest(const Vector3& fragPos, const VertexOut& v0, const VertexOut& v1, const VertexOut& v2)
|
||||
{
|
||||
Vector3 weights;
|
||||
|
||||
weights.x = CrossZ(v2.position, v1.position, fragPos);
|
||||
if ( weights.x > 0 )
|
||||
return std::nullopt;
|
||||
|
||||
weights.y = CrossZ(v0.position, v2.position, fragPos);
|
||||
if ( weights.y > 0 )
|
||||
return std::nullopt;
|
||||
|
||||
weights.z = CrossZ(v1.position, v0.position, fragPos);
|
||||
if ( weights.z > 0 )
|
||||
return std::nullopt;
|
||||
|
||||
const float totalWeight{ weights.x + weights.y + weights.z };
|
||||
|
||||
const float invTotalWeight{ 1.0f / totalWeight };
|
||||
const Vector3 normWeights{
|
||||
weights.x * invTotalWeight,
|
||||
weights.y * invTotalWeight,
|
||||
weights.z * invTotalWeight
|
||||
};
|
||||
|
||||
const float depth =
|
||||
1 / (normWeights.x / v0.position.w +
|
||||
normWeights.y / v1.position.w +
|
||||
normWeights.z / v2.position.w);
|
||||
|
||||
const Vector2 uv =
|
||||
v0.uv * depth * normWeights.x / v0.position.w +
|
||||
v1.uv * depth * normWeights.y / v1.position.w +
|
||||
v2.uv * depth * normWeights.z / v2.position.w;
|
||||
|
||||
const float interpolatedDepth = 1 / (normWeights.x / v0.position.w + normWeights.y / v1.position.w + normWeights.z / v2.position.w);
|
||||
|
||||
auto interpolate =
|
||||
[&]<typename Type>(const Type& val0, const Type& val1, const Type& val2) -> Type
|
||||
{
|
||||
return (val0 / v0.position.w * normWeights.x +
|
||||
val1 / v1.position.w * normWeights.y +
|
||||
val2 / v2.position.w * normWeights.z) * interpolatedDepth;
|
||||
|
||||
};
|
||||
|
||||
//Invert the normal
|
||||
const Vector3 normal = interpolate(v0.normal, v1.normal, v2.normal).Normalized();
|
||||
const Vector3 tangent = interpolate(v0.tangent, v1.tangent, v2.tangent).Normalized();
|
||||
const Vector3 viewDir = interpolate(v0.viewDir, v1.viewDir, v2.viewDir).Normalized();
|
||||
|
||||
return Sample{
|
||||
.uv = uv,
|
||||
.normal = normal,
|
||||
.tangent = tangent,
|
||||
.viewDirection = viewDir,
|
||||
.depth = depth,
|
||||
.weight = normWeights,
|
||||
.mesh = v0.mesh
|
||||
};
|
||||
}
|
||||
|
||||
28
project/src/HitTest.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef GP1_DIRECTX_HITTEST_H
|
||||
#define GP1_DIRECTX_HITTEST_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include "ColorRGB.h"
|
||||
#include "Math/Vector3.h"
|
||||
#include "Math/Vector2.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
|
||||
struct Sample
|
||||
{
|
||||
Vector2 uv{};
|
||||
Vector3 normal{};
|
||||
Vector3 tangent{};
|
||||
Vector3 viewDirection{};
|
||||
float depth{};
|
||||
Vector3 weight{};
|
||||
Mesh* mesh{};
|
||||
};
|
||||
|
||||
|
||||
std::optional<Sample> TriangleHitTest(const Vector3& fragPos, const VertexOut& v0, const VertexOut& v1, const VertexOut& v2);
|
||||
|
||||
#endif //GP1_DIRECTX_HITTEST_H
|
||||
@@ -164,5 +164,10 @@ namespace dae {
|
||||
if (index == 1) return y;
|
||||
return z;
|
||||
}
|
||||
|
||||
bool Vector3::operator==(const Vector3 &v) const {
|
||||
return (x - v.x) < FLT_EPSILON && (y - v.y) < FLT_EPSILON && (z - v.z) < FLT_EPSILON;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace dae
|
||||
Vector3& operator*=(float scale);
|
||||
float& operator[](int index);
|
||||
float operator[](int index) const;
|
||||
bool operator==(const Vector3& v) const;
|
||||
|
||||
|
||||
static const Vector3 UnitX;
|
||||
static const Vector3 UnitY;
|
||||
|
||||
@@ -98,5 +98,14 @@ namespace dae
|
||||
if (index == 2)return z;
|
||||
return w;
|
||||
}
|
||||
|
||||
bool Vector4::operator==(const Vector4 &v) const {
|
||||
return
|
||||
std::abs(x - v.x) <= FLT_EPSILON &&
|
||||
std::abs(y - v.y) <= FLT_EPSILON &&
|
||||
std::abs(z - v.z) <= FLT_EPSILON &&
|
||||
std::abs(w - v.w) <= FLT_EPSILON;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
}
|
||||
@@ -32,5 +32,6 @@ namespace dae
|
||||
Vector4& operator+=(const Vector4& v);
|
||||
float& operator[](int index);
|
||||
float operator[](int index) const;
|
||||
bool operator==(const Vector4& v) const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -136,3 +136,12 @@ void Mesh::SetWorldMatrix(const Matrix &matrix) {
|
||||
void Mesh::ToggleNormals() {
|
||||
m_EffectPtr->ToggleNormals();
|
||||
}
|
||||
|
||||
void Mesh::SetMaterial(Material *pMaterial) {
|
||||
m_Material.reset(pMaterial);
|
||||
m_EffectPtr->SetMaterial(pMaterial);
|
||||
}
|
||||
|
||||
void Mesh::CycleCullMode() {
|
||||
m_EffectPtr->NextCullMode();
|
||||
}
|
||||
@@ -13,6 +13,11 @@ using namespace dae;
|
||||
struct VertexIn;
|
||||
struct VertexOut;
|
||||
|
||||
enum class PrimitiveTopology {
|
||||
TriangleList,
|
||||
TriangleStrip
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -33,8 +38,21 @@ public:
|
||||
|
||||
void NextSamplingState();
|
||||
|
||||
Material* GetMaterial() const { return m_Material.get(); }
|
||||
|
||||
void SetWorldMatrix(const Matrix &matrix);
|
||||
|
||||
std::vector<VertexIn>& GetVertices() { return m_VerticesIn; }
|
||||
std::vector<Uint32>& GetIndices() { return m_Indices; }
|
||||
PrimitiveTopology GetPrimitiveTopology() const { return m_PrimitiveTopology; }
|
||||
|
||||
void SetMaterial(Material *pMaterial);
|
||||
|
||||
void CycleCullMode();
|
||||
|
||||
void SetShouldRender(bool shouldRender) { m_ShouldRender = shouldRender; }
|
||||
bool GetShouldRender() const { return m_ShouldRender; }
|
||||
|
||||
private:
|
||||
BaseEffect *m_EffectPtr;
|
||||
|
||||
@@ -49,6 +67,10 @@ private:
|
||||
UINT m_IndicesCount;
|
||||
|
||||
std::shared_ptr<Material> m_Material{};
|
||||
|
||||
PrimitiveTopology m_PrimitiveTopology{PrimitiveTopology::TriangleList};
|
||||
|
||||
bool m_ShouldRender{ true };
|
||||
};
|
||||
|
||||
struct VertexIn {
|
||||
@@ -65,5 +87,7 @@ struct VertexOut {
|
||||
Vector3 normal{};
|
||||
Vector3 tangent{};
|
||||
Vector3 viewDir{};
|
||||
Mesh* mesh{};
|
||||
bool valid{ true };
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Texture.h"
|
||||
#include "Effects/Effect.h"
|
||||
#include "Effects/FireEffect.h"
|
||||
#include "HitTest.h"
|
||||
|
||||
namespace dae {
|
||||
|
||||
@@ -63,6 +64,23 @@ namespace dae {
|
||||
FireEffect* fireEffect = new FireEffect(m_DevicePtr, L"resources/Fire.fx");
|
||||
m_meshes.push_back(new Mesh(m_DevicePtr, vertices, indices, FireMaterial, fireEffect));
|
||||
|
||||
m_pFireMesh = m_meshes.back();
|
||||
|
||||
//
|
||||
// std::vector<std::unique_ptr<Utils::MaterialMesh>> materialMeshes;
|
||||
// Utils::LoadObjWithMaterials("resources/scene.obj", materialMeshes, true, m_DevicePtr);
|
||||
// for (const auto &mesh: materialMeshes) {
|
||||
// if(mesh->vertices.size() > 0) {
|
||||
// Effect *effect = new Effect(m_DevicePtr, L"resources/SimpleDiffuse.fx");
|
||||
// std::shared_ptr<Material> material = std::make_shared<Material>();
|
||||
// material->diffuseTexturePtr = Texture::LoadFromFile("./resources/" + mesh->diffuse_texture, m_DevicePtr);
|
||||
// m_meshes.push_back(new Mesh(m_DevicePtr, mesh->vertices, mesh->indices, material, effect));
|
||||
// Matrix worldMatrix = m_meshes.back()->GetWorldMatrix();
|
||||
// worldMatrix *= Matrix::CreateScale(2.f, 2.f, 2.f);
|
||||
// m_meshes.back()->SetWorldMatrix(worldMatrix);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
float aspectRatio = static_cast<float>(m_Width) / static_cast<float>(m_Height);
|
||||
m_Camera = Camera({.0f, 5.0f, -64.f}, 45.f);
|
||||
@@ -90,6 +108,12 @@ namespace dae {
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
//SDL
|
||||
|
||||
SDL_FreeSurface(m_pBackBuffer);
|
||||
SDL_FreeSurface(m_pFrontBuffer);
|
||||
|
||||
delete[] m_pDepthBufferPixels;
|
||||
|
||||
}
|
||||
|
||||
@@ -108,42 +132,191 @@ namespace dae {
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::Render() const {
|
||||
void Renderer::Render() {
|
||||
if (!m_IsInitialized)
|
||||
return;
|
||||
if (m_backendType == Backendtype::DirectX) {
|
||||
this->RenderDirectX();
|
||||
} else {
|
||||
this->RenderSDL();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Renderer::RenderDirectX() const {
|
||||
//Clear back buffer
|
||||
if(m_UniformClearColor){
|
||||
const float clearColor[] = {static_cast<float>(r) / 255.f, static_cast<float>(g) / 255.f, static_cast<float>(b) / 255.f, 1.f};
|
||||
m_DeviceContextPtr->ClearRenderTargetView(m_RenderTargetViewPtr, clearColor);
|
||||
} else {
|
||||
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 viewProjMatrix = m_Camera.GetViewProjectionMatrix();
|
||||
for (auto mesh: m_meshes) {
|
||||
if(mesh->GetShouldRender()){
|
||||
Matrix modelMatrix = mesh->GetWorldMatrix();
|
||||
Matrix worldViewProjMatrix = modelMatrix * viewProjMatrix;
|
||||
|
||||
mesh->Render(m_DeviceContextPtr, worldViewProjMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
//Present
|
||||
m_SwapChainPtr->Present(0, 0);
|
||||
}
|
||||
|
||||
void Renderer::RenderSDL() {
|
||||
SDL_FillRect(m_pBackBuffer, nullptr, m_ClearColor);
|
||||
SDL_LockSurface(m_pBackBuffer);
|
||||
std::fill_n(m_pDepthBufferPixels, m_Width * m_Height, std::numeric_limits<float>::max());
|
||||
|
||||
SDL_FillRect(m_pBackBuffer, nullptr, m_ClearColor);
|
||||
|
||||
ColorRGB finalColor{};
|
||||
constexpr int numVerticies = 3;
|
||||
|
||||
m_VerticiesScreenSpace.clear();
|
||||
|
||||
|
||||
for (auto* currentMesh: m_meshes) {
|
||||
|
||||
if(!currentMesh->GetShouldRender()){
|
||||
continue;
|
||||
}
|
||||
|
||||
const Matrix worldViewProjectionMatrix{ currentMesh->GetWorldMatrix() * m_Camera.GetViewProjectionMatrix() };
|
||||
VertexTransformationFunction(worldViewProjectionMatrix, currentMesh, currentMesh->GetVertices(), m_VerticiesScreenSpace);
|
||||
|
||||
int numTriangles{};
|
||||
|
||||
switch (currentMesh->GetPrimitiveTopology()) {
|
||||
case PrimitiveTopology::TriangleList:
|
||||
numTriangles = static_cast<int>(currentMesh->GetIndices().size()) / numVerticies;
|
||||
break;
|
||||
case PrimitiveTopology::TriangleStrip:
|
||||
numTriangles = static_cast<int>(currentMesh->GetIndices().size()) - 2;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (int triangleIndex{}; triangleIndex < numTriangles; ++triangleIndex) {
|
||||
|
||||
VertexOut vertex0, vertex1, vertex2;
|
||||
|
||||
switch (currentMesh->GetPrimitiveTopology()) {
|
||||
case PrimitiveTopology::TriangleList:
|
||||
vertex0 = m_VerticiesScreenSpace[currentMesh->GetIndices()[triangleIndex * numVerticies + 0]];
|
||||
vertex1 = m_VerticiesScreenSpace[currentMesh->GetIndices()[triangleIndex * numVerticies + 1]];
|
||||
vertex2 = m_VerticiesScreenSpace[currentMesh->GetIndices()[triangleIndex * numVerticies + 2]];
|
||||
break;
|
||||
case PrimitiveTopology::TriangleStrip:
|
||||
vertex0 = m_VerticiesScreenSpace[currentMesh->GetIndices()[triangleIndex + 0]];
|
||||
vertex1 = m_VerticiesScreenSpace[currentMesh->GetIndices()[triangleIndex + 1]];
|
||||
vertex2 = m_VerticiesScreenSpace[currentMesh->GetIndices()[triangleIndex + 2]];
|
||||
|
||||
if (triangleIndex % 2 == 1) {
|
||||
std::swap(vertex1, vertex2);
|
||||
}
|
||||
|
||||
if (vertex0.position == vertex1.position ||
|
||||
vertex0.position == vertex2.position ||
|
||||
vertex1.position == vertex2.position) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!vertex0.valid and !vertex1.valid and !vertex2.valid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const float minX{std::min(vertex0.position.x, std::min(vertex1.position.x, vertex2.position.x))};
|
||||
const float minY{std::min(vertex0.position.y, std::min(vertex1.position.y, vertex2.position.y))};
|
||||
|
||||
const float maxX{std::max(vertex0.position.x, std::max(vertex1.position.x, vertex2.position.x))};
|
||||
const float maxY{std::max(vertex0.position.y, std::max(vertex1.position.y, vertex2.position.y))};
|
||||
|
||||
|
||||
const Vector3 side1{vertex1.position - vertex0.position};
|
||||
const Vector3 side2{vertex2.position - vertex0.position};
|
||||
|
||||
const float totalArea{Vector3::Cross(side1, side2).z};
|
||||
|
||||
const int startX = std::max(0, static_cast<int>(minX)) - 1;
|
||||
const int endX = std::min(m_Width - 1, static_cast<int>(maxX)) + 1;
|
||||
|
||||
const int startY = std::max(0, static_cast<int>(minY)) - 1;
|
||||
const int endY = std::min(m_Height - 1, static_cast<int>(maxY)) + 1;
|
||||
|
||||
for (int px{startX}; px < endX; ++px) {
|
||||
for (int py{startY}; py < endY; ++py) {
|
||||
|
||||
if(m_isHitbox){
|
||||
//Hitboxes
|
||||
m_pBackBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
|
||||
static_cast<uint8_t>(255),
|
||||
static_cast<uint8_t>(255),
|
||||
static_cast<uint8_t>(255));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (px < 0 || px >= m_Width || py < 0 || py >= m_Height) {
|
||||
//TEMP fix for out of bounds
|
||||
//This is to remove triangles having an incorrect edge on their bounding box
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector3 P{static_cast<float>(px) + 0.5f, static_cast<float>(py) + 0.5f, 1.f};
|
||||
|
||||
auto sample{ TriangleHitTest(P, vertex0, vertex1, vertex2) };
|
||||
|
||||
if (!sample.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Vector3 fragPos{ static_cast<float>(px) + 0.5f, static_cast<float>(py) + 0.5f, 1.f };
|
||||
|
||||
int depthBufferIndex{ px + (py * m_Width) };
|
||||
|
||||
float min{.985f};
|
||||
float max{1.f};
|
||||
float depthBuffer{(sample.value().depth - min) * (max - min)};
|
||||
float currentDepth = sample.value().depth;
|
||||
|
||||
if (m_pDepthBufferPixels[depthBufferIndex] > currentDepth) {
|
||||
m_pDepthBufferPixels[depthBufferIndex] = currentDepth;
|
||||
|
||||
if (m_isDepthBuffer) {
|
||||
finalColor = ColorRGB{depthBuffer, depthBuffer, depthBuffer};
|
||||
} else {
|
||||
SDL_FillRect(m_pBackBuffer, nullptr, Uint32(255 << 24) + Uint32(100 << 16) + Uint32(100 << 8) + Uint32(100));
|
||||
finalColor = ShadePixel(sample.value());
|
||||
}
|
||||
|
||||
//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);
|
||||
finalColor.MaxToOne();
|
||||
|
||||
m_pBackBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
|
||||
static_cast<uint8_t>(finalColor.r * 255),
|
||||
static_cast<uint8_t>(finalColor.g * 255),
|
||||
static_cast<uint8_t>(finalColor.b * 255));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_BlitSurface(m_pBackBuffer, nullptr, m_pFrontBuffer, nullptr);
|
||||
SDL_UnlockSurface(m_pBackBuffer);
|
||||
SDL_BlitSurface(m_pBackBuffer,nullptr, m_pFrontBuffer, nullptr);
|
||||
SDL_UpdateWindowSurface(m_pWindow);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HRESULT Renderer::InitializeDirectX() {
|
||||
//1. Create device & deviceContext
|
||||
//=====
|
||||
@@ -259,10 +432,163 @@ namespace dae {
|
||||
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];
|
||||
m_pDepthBufferPixels = new float[m_Width * m_Height];
|
||||
}
|
||||
|
||||
|
||||
void Renderer::VertexTransformationFunction(const Matrix &WorldViewProjectionMatrix, Mesh* mesh,
|
||||
std::vector<VertexIn> &vertices_in, std::vector<VertexOut> &vertices_out) const {
|
||||
for (const VertexIn& vert : vertices_in)
|
||||
{
|
||||
VertexOut vertex_out{};
|
||||
|
||||
Vector4 vertPos{ WorldViewProjectionMatrix.TransformPoint({vert.position, 1}) };
|
||||
|
||||
const Vector3 normal{ mesh->GetWorldMatrix().TransformVector(vert.normal) };
|
||||
const Vector3 tangent{ mesh->GetWorldMatrix().TransformVector(vert.tangent) };
|
||||
|
||||
|
||||
|
||||
vertPos.x /= vertPos.w;
|
||||
vertPos.y /= vertPos.w;
|
||||
vertPos.z /= vertPos.w;
|
||||
|
||||
bool isValid{ true };
|
||||
|
||||
//Check if the vertex is inside the screen
|
||||
if (vertPos.x < -1.f || vertPos.x > 1.f ||
|
||||
vertPos.y < -1.f || vertPos.y > 1.f ||
|
||||
vertPos.z < 0.f || vertPos.z > 1.f)
|
||||
isValid = false;
|
||||
|
||||
vertPos.x = ((vertPos.x + 1.f) / 2.f) * static_cast<float>(m_Width);
|
||||
vertPos.y = ((1.f - vertPos.y) / 2.f) * static_cast<float>(m_Height);
|
||||
|
||||
vertex_out.position = vertPos;
|
||||
vertex_out.uv = vert.uv;
|
||||
vertex_out.normal = normal;
|
||||
vertex_out.tangent = tangent;
|
||||
vertex_out.mesh = mesh;
|
||||
// vertex_out.viewDir = WorldViewProjectionMatrix.TransformVector(vert.viewDir);
|
||||
vertex_out.valid = isValid;
|
||||
|
||||
vertices_out.push_back(vertex_out);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Renderer::ToggleDepthBuffer() {
|
||||
m_isDepthBuffer = !m_isDepthBuffer;
|
||||
}
|
||||
|
||||
ColorRGB Renderer::ShadePixel(const Sample &sample) {
|
||||
|
||||
Material* currentMaterial = sample.mesh->GetMaterial();
|
||||
|
||||
if(currentMaterial->normalTexturePtr == nullptr && currentMaterial->specularTexturePtr == nullptr && currentMaterial->glossTexturePtr == nullptr){
|
||||
return currentMaterial->diffuseTexturePtr->Sample(sample.uv);
|
||||
}
|
||||
|
||||
Vector3 lightDirection = { .577f, -.577f, .577f};
|
||||
Vector3 normal = sample.normal.Normalized();
|
||||
constexpr float lightIntensity{ 7.f };
|
||||
|
||||
ColorRGB color{ 1, 1, 1 };
|
||||
constexpr ColorRGB ambient{ .03f, .03f, .03f};
|
||||
|
||||
if(m_useNormals){
|
||||
const ColorRGB normalSample{ sample.mesh->GetMaterial()->normalTexturePtr->Sample(sample.uv) };
|
||||
const Vector4 normalMapSample{
|
||||
2.f * normalSample.r - 1.f,
|
||||
2.f * normalSample.g - 1.f,
|
||||
2.f * normalSample.b - 1.f,
|
||||
0.f
|
||||
};
|
||||
|
||||
const Vector3 biNormal{ Vector3::Cross(normal, sample.tangent) };
|
||||
const Matrix tangentToWorld{
|
||||
Vector4{ sample.tangent, 0.f },
|
||||
Vector4{ biNormal, 0.f },
|
||||
Vector4{ normal, 0.f },
|
||||
Vector4{ 0.f, 0.f, 0.f, 1.f }
|
||||
};
|
||||
normal = tangentToWorld.TransformVector(normalMapSample).Normalized();
|
||||
}
|
||||
|
||||
|
||||
const ColorRGB diffuseSample{ currentMaterial->diffuseTexturePtr->Sample(sample.uv) };
|
||||
double invPi = 1.0 / PI;
|
||||
const ColorRGB lambert{ diffuseSample * lightIntensity * invPi };
|
||||
|
||||
//TODO: ask why deviding by PI causses Segmentation fault
|
||||
// const ColorRGB lambert{ diffuseSample * lightIntensity / PI };
|
||||
|
||||
|
||||
float specularReflectance{ 1.f };
|
||||
float shininess{ 25.f };
|
||||
|
||||
specularReflectance *= currentMaterial->glossTexturePtr->Sample(sample.uv).r;
|
||||
shininess *= currentMaterial->specularTexturePtr->Sample(sample.uv).r;
|
||||
|
||||
const float cosAngle = Vector3::Dot(normal, -lightDirection);
|
||||
|
||||
const ColorRGB specular = specularReflectance * powf(cosAngle, shininess) * colors::White;
|
||||
|
||||
if (cosAngle < 0) {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
switch(m_ShadeMode){
|
||||
case ShadeMode::ObservedArea:
|
||||
break;
|
||||
case ShadeMode::Diffuse:
|
||||
color = lambert;
|
||||
break;
|
||||
case ShadeMode::Specular:
|
||||
color = specular;
|
||||
break;
|
||||
case ShadeMode::Combined:
|
||||
color = lambert + specular + ambient;
|
||||
break;
|
||||
}
|
||||
|
||||
color *= ColorRGB{ cosAngle, cosAngle, cosAngle };
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void Renderer::CycleCullMode() {
|
||||
for(auto mesh: m_meshes){
|
||||
mesh->CycleCullMode();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::ToggleBoundingBox() {
|
||||
m_isHitbox = !m_isHitbox;
|
||||
}
|
||||
|
||||
void Renderer::CycleRenderingMode() {
|
||||
switch (m_ShadeMode) {
|
||||
case ShadeMode::ObservedArea:
|
||||
m_ShadeMode = ShadeMode::Diffuse;
|
||||
std::cout << "Diffuse" << std::endl;
|
||||
break;
|
||||
case ShadeMode::Diffuse:
|
||||
m_ShadeMode = ShadeMode::Specular;
|
||||
std::cout << "Specular" << std::endl;
|
||||
break;
|
||||
case ShadeMode::Specular:
|
||||
m_ShadeMode = ShadeMode::Combined;
|
||||
std::cout << "Combined" << std::endl;
|
||||
break;
|
||||
case ShadeMode::Combined:
|
||||
m_ShadeMode = ShadeMode::ObservedArea;
|
||||
std::cout << "Observed Area" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SwitchBackend() {
|
||||
if (m_backendType == Backendtype::DirectX) {
|
||||
m_backendType = Backendtype::SDL;
|
||||
@@ -278,6 +604,7 @@ namespace dae {
|
||||
}
|
||||
|
||||
void Renderer::ToggleNormals() {
|
||||
m_useNormals = !m_useNormals;
|
||||
for(auto mesh: m_meshes){
|
||||
mesh->ToggleNormals();
|
||||
}
|
||||
@@ -290,4 +617,10 @@ namespace dae {
|
||||
void Renderer::ToggleUniformClearColor() {
|
||||
m_UniformClearColor = !m_UniformClearColor;
|
||||
}
|
||||
|
||||
void Renderer::ToggleFireFX() {
|
||||
m_pFireMesh->SetShouldRender(!m_pFireMesh->GetShouldRender());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Mesh.h"
|
||||
#include "Camera.h"
|
||||
#include "HitTest.h"
|
||||
|
||||
struct SDL_Window;
|
||||
struct SDL_Surface;
|
||||
@@ -11,12 +12,19 @@ enum class Backendtype {
|
||||
SDL
|
||||
};
|
||||
|
||||
enum class ShadeMode{
|
||||
ObservedArea,
|
||||
Diffuse,
|
||||
Specular,
|
||||
Combined
|
||||
};
|
||||
|
||||
namespace dae
|
||||
{
|
||||
class Renderer final
|
||||
{
|
||||
public:
|
||||
Renderer(SDL_Window* pWindow);
|
||||
explicit Renderer(SDL_Window* pWindow);
|
||||
~Renderer();
|
||||
|
||||
Renderer(const Renderer&) = delete;
|
||||
@@ -25,7 +33,7 @@ namespace dae
|
||||
Renderer& operator=(Renderer&&) noexcept = delete;
|
||||
|
||||
void Update(const Timer* pTimer);
|
||||
void Render() const;
|
||||
void Render();
|
||||
|
||||
//Switching Functions
|
||||
void NextSamplingState();
|
||||
@@ -37,31 +45,23 @@ namespace dae
|
||||
|
||||
void ToggleUniformClearColor();
|
||||
|
||||
void ToggleDepthBuffer();
|
||||
|
||||
void CycleCullMode();
|
||||
|
||||
void ToggleBoundingBox();
|
||||
|
||||
void CycleRenderingMode();
|
||||
|
||||
void ToggleFireFX();
|
||||
|
||||
private:
|
||||
// Common vars
|
||||
SDL_Window* m_pWindow{};
|
||||
|
||||
int m_Width{};
|
||||
int m_Height{};
|
||||
|
||||
bool m_IsInitialized{ false };
|
||||
|
||||
//DIRECTX
|
||||
HRESULT InitializeDirectX();
|
||||
void InitializeSDLRasterizer();
|
||||
|
||||
ID3D11Device* m_DevicePtr{};
|
||||
ID3D11DeviceContext* m_DeviceContextPtr{};
|
||||
IDXGISwapChain* m_SwapChainPtr{};
|
||||
ID3D11Texture2D* m_DepthStencilBufferPtr{};
|
||||
ID3D11DepthStencilView* m_DepthStencilViewPtr{};
|
||||
ID3D11Resource* m_RenderTargetBufferPtr{};
|
||||
ID3D11RenderTargetView* m_RenderTargetViewPtr{};
|
||||
|
||||
SDL_Surface* m_pFrontBuffer{ nullptr };
|
||||
SDL_Surface* m_pBackBuffer{ nullptr };
|
||||
uint32_t* m_pBackBufferPixels{};
|
||||
|
||||
|
||||
std::vector<Mesh*> m_meshes{};
|
||||
std::vector<std::shared_ptr<Material>> m_materials{};
|
||||
|
||||
@@ -73,5 +73,51 @@ namespace dae
|
||||
float m_currentRotation{};
|
||||
bool m_UniformClearColor{ false };
|
||||
|
||||
|
||||
//DirectX vars
|
||||
|
||||
bool m_IsInitialized{ false };
|
||||
|
||||
HRESULT InitializeDirectX();
|
||||
void RenderDirectX() const;
|
||||
|
||||
//Storing the mesh so i can deactivate it;
|
||||
Mesh* m_pFireMesh{};
|
||||
|
||||
ID3D11Device* m_DevicePtr{};
|
||||
ID3D11DeviceContext* m_DeviceContextPtr{};
|
||||
IDXGISwapChain* m_SwapChainPtr{};
|
||||
ID3D11Texture2D* m_DepthStencilBufferPtr{};
|
||||
ID3D11DepthStencilView* m_DepthStencilViewPtr{};
|
||||
ID3D11Resource* m_RenderTargetBufferPtr{};
|
||||
ID3D11RenderTargetView* m_RenderTargetViewPtr{};
|
||||
|
||||
//SDL vars
|
||||
|
||||
void InitializeSDLRasterizer();
|
||||
void RenderSDL();
|
||||
void VertexTransformationFunction(const Matrix& WorldViewProjectionMatrix, Mesh* mesh, std::vector<VertexIn> &vertices_in, std::vector<VertexOut> &vertices_out) const;
|
||||
ColorRGB ShadePixel(const Sample& sample);
|
||||
|
||||
|
||||
SDL_Surface* m_pFrontBuffer{ nullptr };
|
||||
SDL_Surface* m_pBackBuffer{ nullptr };
|
||||
uint32_t* m_pBackBufferPixels{};
|
||||
|
||||
bool m_useNormals{ true };
|
||||
bool m_isHitbox{ false };
|
||||
ShadeMode m_ShadeMode{ ShadeMode::Combined };
|
||||
bool m_isDepthBuffer{ false };
|
||||
|
||||
|
||||
Uint8 r{100};
|
||||
Uint8 g{100};
|
||||
Uint8 b{100};
|
||||
Uint32 m_ClearColor{ Uint32(255 << 24) + Uint32(r << 16) + Uint32(g << 8) + Uint32(b) };
|
||||
float* m_pDepthBufferPixels{};
|
||||
|
||||
std::vector<VertexOut> m_VerticiesScreenSpace{};
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include "Texture.h"
|
||||
|
||||
Texture::~Texture() {
|
||||
@@ -11,6 +12,11 @@ Texture *Texture::LoadFromFile(const std::string &path, ID3D11Device *devicePtr)
|
||||
std::cerr << "Failed to load texture: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
if (surface->format->BytesPerPixel != 4)
|
||||
{
|
||||
std::cerr << "Texture::LoadFromFile > Texture is not in the right format: " << path << std::endl;
|
||||
// throw std::runtime_error("Texture is not in the right format");
|
||||
}
|
||||
|
||||
auto *texture = new Texture(surface, devicePtr);
|
||||
|
||||
@@ -46,6 +52,22 @@ Texture::Texture(SDL_Surface *surfacePtr, ID3D11Device *devicePtr) {
|
||||
|
||||
hr = devicePtr->CreateShaderResourceView(m_TexturePtr, &SRVDesc, &m_TextureResourceViewPtr);
|
||||
|
||||
SDL_FreeSurface(surfacePtr);
|
||||
|
||||
m_SurfacePtr = surfacePtr;
|
||||
m_pSurfacePixels = static_cast<Uint32 *>(surfacePtr->pixels);
|
||||
}
|
||||
|
||||
ColorRGB Texture::Sample(const Vector2 &uv) const {
|
||||
Uint8 red, green, blue;
|
||||
|
||||
Vector2 wrapped = {fmod(uv.x, 1.0f), fmod(uv.y, 1.0f)};
|
||||
|
||||
if (wrapped.x < 0.0f) wrapped.x += 1.0f;
|
||||
if (wrapped.y < 0.0f) wrapped.y += 1.0f;
|
||||
|
||||
SDL_GetRGB(m_pSurfacePixels[
|
||||
static_cast<int>(wrapped.x * static_cast<float>(m_SurfacePtr->w - 1)) +
|
||||
static_cast<int>(wrapped.y * static_cast<float>(m_SurfacePtr->h - 1)) * (m_SurfacePtr->w)
|
||||
], m_SurfacePtr->format, &red, &green, &blue);
|
||||
|
||||
return ColorRGB{static_cast<float>(red) / 255.0f, static_cast<float>(green) / 255.0f, static_cast<float>(blue) / 255.0f};
|
||||
}
|
||||
@@ -7,7 +7,10 @@
|
||||
#include "Texture.h"
|
||||
#include "SDL_surface.h"
|
||||
#include "SDL_image.h"
|
||||
#include "ColorRGB.h"
|
||||
#include "Math/Vector2.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
@@ -17,11 +20,16 @@ public:
|
||||
|
||||
inline ID3D11ShaderResourceView* GetSrv() const { return m_TextureResourceViewPtr; }
|
||||
|
||||
ColorRGB Sample(const Vector2& uv) const;
|
||||
|
||||
private:
|
||||
Texture(SDL_Surface* surfacePtr, ID3D11Device* devicePtr);
|
||||
|
||||
ID3D11ShaderResourceView* m_TextureResourceViewPtr{};
|
||||
ID3D11Texture2D* m_TexturePtr{};
|
||||
|
||||
SDL_Surface* m_SurfacePtr{ nullptr };
|
||||
uint32_t* m_pSurfacePixels{ nullptr };
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -256,5 +256,118 @@ namespace dae {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct MaterialMesh {
|
||||
std::vector<VertexIn> vertices;
|
||||
std::vector<uint32_t> indices;
|
||||
int material_id = -1; // Material ID associated with this mesh
|
||||
std::string diffuse_texture; // Path to the diffuse texture
|
||||
};
|
||||
|
||||
|
||||
static bool LoadObjWithMaterials(const std::string &fileName, std::vector<std::unique_ptr<MaterialMesh>> &meshes,
|
||||
bool flipAxisAndWinding = true, ID3D11Device* device = nullptr) {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
std::string warn, err;
|
||||
|
||||
std::string basepath = "resources/";
|
||||
|
||||
if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, fileName.c_str(), basepath.c_str())) {
|
||||
if (!warn.empty()) {
|
||||
std::cerr << "Warning: " << warn << std::endl;
|
||||
}
|
||||
if (!err.empty()) {
|
||||
std::cerr << "Error: " << err << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clear and prepare the meshes array
|
||||
meshes.clear();
|
||||
|
||||
// Create Mesh objects for each material
|
||||
meshes.resize(materials.size());
|
||||
for (size_t i = 0; i < materials.size(); ++i) {
|
||||
meshes[i] = std::make_unique<MaterialMesh>();
|
||||
meshes[i]->material_id = static_cast<int>(i);
|
||||
meshes[i]->diffuse_texture = materials[i].diffuse_texname;
|
||||
}
|
||||
|
||||
// Default Mesh for faces with no material
|
||||
auto defaultMesh = std::make_unique<MaterialMesh>();
|
||||
defaultMesh->material_id = -1;
|
||||
defaultMesh->diffuse_texture = "";
|
||||
meshes.push_back(std::move(defaultMesh));
|
||||
|
||||
for (const auto &shape : shapes) {
|
||||
size_t index_offset = 0;
|
||||
|
||||
for (size_t f = 0; f < shape.mesh.num_face_vertices.size(); f++) {
|
||||
auto fv = size_t(shape.mesh.num_face_vertices[f]);
|
||||
|
||||
if (fv != 3) {
|
||||
std::cerr << "Error: Only triangular faces are supported." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int material_id = (f < shape.mesh.material_ids.size()) ? shape.mesh.material_ids[f] : -1;
|
||||
if (material_id < 0 || material_id >= static_cast<int>(materials.size())) {
|
||||
material_id = -1;
|
||||
}
|
||||
|
||||
auto* targetMesh = (material_id >= 0 && material_id < static_cast<int>(materials.size()))
|
||||
? meshes[material_id].get()
|
||||
: meshes.back().get(); // Use default mesh
|
||||
|
||||
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];
|
||||
|
||||
VertexIn vertex;
|
||||
|
||||
if (idx.vertex_index >= 0) {
|
||||
vertex.position = Vector3(
|
||||
attrib.vertices[3 * idx.vertex_index + 0],
|
||||
attrib.vertices[3 * idx.vertex_index + 1],
|
||||
attrib.vertices[3 * idx.vertex_index + 2]
|
||||
);
|
||||
}
|
||||
|
||||
if (idx.texcoord_index >= 0) {
|
||||
vertex.uv = Vector2(
|
||||
attrib.texcoords[2 * idx.texcoord_index + 0],
|
||||
1.0f - attrib.texcoords[2 * idx.texcoord_index + 1] // Flip V
|
||||
);
|
||||
}
|
||||
|
||||
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]
|
||||
);
|
||||
}
|
||||
|
||||
tempVertices[v] = vertex;
|
||||
tempIndices[v] = static_cast<uint32_t>(targetMesh->vertices.size());
|
||||
targetMesh->vertices.push_back(vertex);
|
||||
}
|
||||
|
||||
// Push indices in the default order
|
||||
targetMesh->indices.push_back(tempIndices[0]);
|
||||
targetMesh->indices.push_back(tempIndices[1]);
|
||||
targetMesh->indices.push_back(tempIndices[2]);
|
||||
|
||||
index_offset += fv;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ int main(int argc, char *args[]) {
|
||||
const uint32_t width = 640;
|
||||
const uint32_t height = 480;
|
||||
|
||||
|
||||
SDL_Window *pWindow = SDL_CreateWindow(
|
||||
"DirectX - Bram Verhulst - 2GD11E",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
@@ -49,6 +50,8 @@ int main(int argc, char *args[]) {
|
||||
const auto pTimer = new Timer();
|
||||
const auto pRenderer = new Renderer(pWindow);
|
||||
|
||||
bool printFPS = false;
|
||||
|
||||
//Start loop
|
||||
pTimer->Start();
|
||||
float printTimer = 0.f;
|
||||
@@ -73,6 +76,7 @@ int main(int argc, char *args[]) {
|
||||
}
|
||||
if(scancode == SDL_SCANCODE_F9){
|
||||
// Cycle Cull mode
|
||||
pRenderer->CycleCullMode();
|
||||
}
|
||||
if(scancode == SDL_SCANCODE_F10){
|
||||
// Toggle Uniform Clear Color
|
||||
@@ -80,11 +84,13 @@ int main(int argc, char *args[]) {
|
||||
}
|
||||
if(scancode == SDL_SCANCODE_F11){
|
||||
// toggle Print fps
|
||||
printFPS = !printFPS;
|
||||
}
|
||||
|
||||
//Hardware
|
||||
if (scancode == SDL_SCANCODE_F3){
|
||||
// Toggle FireFX mesh
|
||||
pRenderer->ToggleFireFX();
|
||||
}
|
||||
if (scancode == SDL_SCANCODE_F4){
|
||||
//Toggle texture sampling states
|
||||
@@ -93,25 +99,21 @@ int main(int argc, char *args[]) {
|
||||
//Software
|
||||
if(scancode == SDL_SCANCODE_F5){
|
||||
//Cycle shading mode
|
||||
pRenderer->CycleRenderingMode();
|
||||
}
|
||||
if(scancode == SDL_SCANCODE_F6){
|
||||
//Toggle normal mapping
|
||||
pRenderer->ToggleNormals();
|
||||
}
|
||||
if(scancode == SDL_SCANCODE_F7){
|
||||
//Toggle Depth Buffer
|
||||
pRenderer->ToggleDepthBuffer();
|
||||
}
|
||||
if(scancode == SDL_SCANCODE_F8) {
|
||||
//Toggle BoundingBox
|
||||
pRenderer->ToggleBoundingBox();
|
||||
}
|
||||
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_F2) {
|
||||
}
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_F3) {
|
||||
|
||||
}
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_F4) {
|
||||
pRenderer->ToggleNormals();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -129,7 +131,7 @@ int main(int argc, char *args[]) {
|
||||
//--------- Timer ---------
|
||||
pTimer->Update();
|
||||
printTimer += pTimer->GetElapsed();
|
||||
if (printTimer >= 1.f) {
|
||||
if (printTimer >= 1.f && printFPS) {
|
||||
printTimer = 0.f;
|
||||
std::cout << "dFPS: " << pTimer->GetdFPS() << std::endl;
|
||||
}
|
||||
|
||||