Last week of rasterizer
:p silly cats FTW
This commit is contained in:
@@ -21,8 +21,6 @@ set(IMGUI_SOURCES
|
||||
"imgui/backends/imgui_impl_sdlrenderer2.cpp"
|
||||
)
|
||||
|
||||
|
||||
|
||||
# Create the executable
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
#add_executable(${PROJECT_NAME} ${SOURCES} ${IMGUI_SOURCES})
|
||||
|
||||
BIN
project/resources/cat.png
Normal file
BIN
project/resources/cat.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
@@ -40,9 +40,10 @@ namespace dae {
|
||||
float zNear{.1f};
|
||||
float zFar{100.f};
|
||||
|
||||
void Initialize(float _fovAngle = 90.f, Vector3 _origin = {0.f, 0.f, 0.f}) {
|
||||
void Initialize(float _fovAngle = 90.f, Vector3 _origin = {0.f, 0.f, 0.f}, float _aspect = 1.f) {
|
||||
fovAngle = _fovAngle;
|
||||
fov = tanf((fovAngle * TO_RADIANS) / 2.f);
|
||||
aspect = _aspect;
|
||||
|
||||
origin = _origin;
|
||||
}
|
||||
@@ -54,15 +55,14 @@ namespace dae {
|
||||
|
||||
void CalculateViewMatrix() {
|
||||
|
||||
viewMatrix = Matrix::CreateLookAtLH(origin, forward, up);
|
||||
invViewMatrix = Matrix::Inverse(viewMatrix);
|
||||
viewMatrix = Matrix::CreateLookAtLH(origin, origin + forward, Vector3::UnitY);
|
||||
Matrix temp = viewMatrix;
|
||||
|
||||
//TODO W1
|
||||
//ONB => invViewMatrix
|
||||
//Inverse(ONB) => ViewMatrix
|
||||
invViewMatrix = temp.Inverse();
|
||||
|
||||
//ViewMatrix => Matrix::CreateLookAtLH(...) [not implemented yet]
|
||||
//DirectX Implementation => https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixlookatlh
|
||||
right = invViewMatrix.GetAxisX();
|
||||
up = invViewMatrix.GetAxisY();
|
||||
forward = invViewMatrix.GetAxisZ();
|
||||
}
|
||||
|
||||
void CalculateProjectionMatrix() {
|
||||
@@ -84,31 +84,38 @@ namespace dae {
|
||||
|
||||
float MovementSpeed{ 10.f };
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_LSHIFT]) {
|
||||
if (pKeyboardState[SDL_SCANCODE_LSHIFT])
|
||||
{
|
||||
MovementSpeed *= 2;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_W]) {
|
||||
if (pKeyboardState[SDL_SCANCODE_W])
|
||||
{
|
||||
origin += forward * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_A]) {
|
||||
if (pKeyboardState[SDL_SCANCODE_A])
|
||||
{
|
||||
origin -= right * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_S]) {
|
||||
if (pKeyboardState[SDL_SCANCODE_S])
|
||||
{
|
||||
origin -= forward * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_D]) {
|
||||
if (pKeyboardState[SDL_SCANCODE_D])
|
||||
{
|
||||
origin += right * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_E]) {
|
||||
if (pKeyboardState[SDL_SCANCODE_E])
|
||||
{
|
||||
origin += up * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
if (pKeyboardState[SDL_SCANCODE_Q]) {
|
||||
if (pKeyboardState[SDL_SCANCODE_Q])
|
||||
{
|
||||
origin -= up * deltaTime * MovementSpeed;
|
||||
}
|
||||
|
||||
@@ -125,13 +132,16 @@ namespace dae {
|
||||
totalPitch += (static_cast<float>(mouseY) * mouseSens) * TO_RADIANS;
|
||||
|
||||
mousePosChange = true;
|
||||
} else if (mouseState == SDL_BUTTON_LEFT) {
|
||||
}
|
||||
else if (mouseState == SDL_BUTTON_LEFT)
|
||||
{
|
||||
zDirection = forward.Normalized() * static_cast<float>(-mouseY);
|
||||
|
||||
totalYaw += static_cast<float>(mouseX) * mouseSens * TO_RADIANS;
|
||||
|
||||
mousePosChange = true;
|
||||
} else if (mouseState == SDL_BUTTON_X2) //lmb + rmb
|
||||
}
|
||||
else if (mouseState == SDL_BUTTON_X2) //lmb + rmb
|
||||
{
|
||||
origin.y += static_cast<float>(mouseY) / 2;
|
||||
|
||||
@@ -140,7 +150,8 @@ namespace dae {
|
||||
|
||||
origin += ((zDirection + xDirection + yDirection) * cameraSpeed * deltaTime);
|
||||
|
||||
if (mousePosChange) {
|
||||
if (mousePosChange)
|
||||
{
|
||||
const Matrix yawMatrix{ Matrix::CreateRotationY(totalYaw) };
|
||||
const Matrix pitchMatrix{ Matrix::CreateRotationX(totalPitch) };
|
||||
|
||||
@@ -152,6 +163,7 @@ namespace dae {
|
||||
//Update Matrices
|
||||
CalculateViewMatrix();
|
||||
CalculateProjectionMatrix(); //Try to optimize this - should only be called once or when fov/aspectRatio changes
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "MathHelpers.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace dae
|
||||
{
|
||||
|
||||
@@ -7,23 +7,24 @@
|
||||
namespace dae
|
||||
{
|
||||
struct Vertex
|
||||
{
|
||||
Vector3 position{};
|
||||
ColorRGB color{colors::White};
|
||||
Vector2 uv{}; //W2
|
||||
//Vector3 normal{}; //W4
|
||||
//Vector3 tangent{}; //W4
|
||||
//Vector3 viewDirection{}; //W4
|
||||
};
|
||||
|
||||
struct Vertex_Out
|
||||
{
|
||||
Vector4 position{};
|
||||
ColorRGB color{colors::White};
|
||||
Vector2 uv{};
|
||||
//Vector3 normal{};
|
||||
//Vector3 tangent{};
|
||||
//Vector3 viewDirection{};
|
||||
bool valid{ true };
|
||||
Vector3 normal{};
|
||||
Vector3 tangent{};
|
||||
Vector3 viewDir{};
|
||||
};
|
||||
|
||||
struct Sample
|
||||
{
|
||||
Vector2 uv{};
|
||||
Vector3 normal{};
|
||||
Vector3 tangent{};
|
||||
Vector3 viewDirection{};
|
||||
float depth{};
|
||||
Vector3 weight{};
|
||||
};
|
||||
|
||||
enum class PrimitiveTopology
|
||||
@@ -36,9 +37,9 @@ namespace dae
|
||||
{
|
||||
std::vector<Vertex> vertices{};
|
||||
std::vector<uint32_t> indices{};
|
||||
PrimitiveTopology primitiveTopology{ PrimitiveTopology::TriangleStrip };
|
||||
PrimitiveTopology primitiveTopology{ PrimitiveTopology::TriangleList };
|
||||
|
||||
std::vector<Vertex_Out> vertices_out{};
|
||||
std::vector<Vertex> vertices_out{};
|
||||
Matrix worldMatrix{};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,11 +15,84 @@ float max(float a, float b, float c) {
|
||||
|
||||
float CrossZ(const Vector3& p0, const Vector3& p1, const Vector3& point)
|
||||
{
|
||||
return (point.x - p0.x) * (p1.y - p0.y)
|
||||
- (point.y - p0.y) * (p1.x - p0.x);
|
||||
return (p1.x - p0.x) * (point.y - p0.y)
|
||||
- (p1.y - p0.y) * (point.x - p0.x);
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
Type interpolate(const Type& val0, const Type& val1, const Type& val2, float depth, float weight)
|
||||
{
|
||||
return {
|
||||
val0 * depth * weight +
|
||||
val1 * depth * weight +
|
||||
val2 * depth * weight
|
||||
};
|
||||
}
|
||||
|
||||
std::optional<Sample> HitTest::TriangleHitTest(const Vector3& fragPos, const Vertex& v0, const Vertex& v1, const Vertex& 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
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
HitTest::HitTestSample HitTest::Triangle(const Vector3 &pos, const std::vector<Vertex> &vertices) {
|
||||
float minX = min(vertices[0].position.x, vertices[1].position.x, vertices[2].position.x);
|
||||
float maxX = max(vertices[0].position.x, vertices[1].position.x, vertices[2].position.x);
|
||||
@@ -46,9 +119,10 @@ HitTest::HitTestSample HitTest::Triangle(const Vector3 &pos, const std::vector<V
|
||||
}
|
||||
|
||||
const double totalWeight{ w0 + w1 + w2 };
|
||||
w0 /= totalWeight;
|
||||
w1 /= totalWeight;
|
||||
w2 /= totalWeight;
|
||||
const float invTotalWeight{ static_cast<float>(1.0f / totalWeight) };
|
||||
w0 *= invTotalWeight;
|
||||
w1 *= invTotalWeight;
|
||||
w2 *= invTotalWeight;
|
||||
|
||||
|
||||
assert(std::abs(w0 + w1 + w2 - 1) < 0.0001);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef GP1_RASTERIZER_HITTEST_H
|
||||
#define GP1_RASTERIZER_HITTEST_H
|
||||
|
||||
#include <optional>
|
||||
#include "DataTypes.h"
|
||||
#include "Maths.h"
|
||||
|
||||
@@ -17,6 +18,9 @@ namespace HitTest {
|
||||
};
|
||||
|
||||
HitTestSample Triangle(const Vector3& pos, const std::vector<Vertex>& vertices);
|
||||
|
||||
|
||||
std::optional<Sample> TriangleHitTest(const Vector3& fragPos, const Vertex& v0, const Vertex& v1, const Vertex& v2);
|
||||
}
|
||||
|
||||
#endif //GP1_RASTERIZER_HITTEST_H
|
||||
|
||||
@@ -7,33 +7,28 @@
|
||||
|
||||
namespace dae {
|
||||
Matrix::Matrix(const Vector3 &xAxis, const Vector3 &yAxis, const Vector3 &zAxis, const Vector3 &t) :
|
||||
Matrix({ xAxis, 0 }, { yAxis, 0 }, { zAxis, 0 }, { t, 1 })
|
||||
{
|
||||
Matrix({xAxis, 0}, {yAxis, 0}, {zAxis, 0}, {t, 1}) {
|
||||
}
|
||||
|
||||
Matrix::Matrix(const Vector4& xAxis, const Vector4& yAxis, const Vector4& zAxis, const Vector4& t)
|
||||
{
|
||||
Matrix::Matrix(const Vector4 &xAxis, const Vector4 &yAxis, const Vector4 &zAxis, const Vector4 &t) {
|
||||
data[0] = xAxis;
|
||||
data[1] = yAxis;
|
||||
data[2] = zAxis;
|
||||
data[3] = t;
|
||||
}
|
||||
|
||||
Matrix::Matrix(const Matrix& m)
|
||||
{
|
||||
Matrix::Matrix(const Matrix &m) {
|
||||
data[0] = m[0];
|
||||
data[1] = m[1];
|
||||
data[2] = m[2];
|
||||
data[3] = m[3];
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformVector(const Vector3& v) const
|
||||
{
|
||||
Vector3 Matrix::TransformVector(const Vector3 &v) const {
|
||||
return TransformVector(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformVector(float x, float y, float z) const
|
||||
{
|
||||
Vector3 Matrix::TransformVector(float x, float y, float z) const {
|
||||
return Vector3{
|
||||
data[0].x * x + data[1].x * y + data[2].x * z,
|
||||
data[0].y * x + data[1].y * y + data[2].y * z,
|
||||
@@ -41,13 +36,11 @@ namespace dae {
|
||||
};
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformPoint(const Vector3& p) const
|
||||
{
|
||||
Vector3 Matrix::TransformPoint(const Vector3 &p) const {
|
||||
return TransformPoint(p.x, p.y, p.z);
|
||||
}
|
||||
|
||||
Vector3 Matrix::TransformPoint(float x, float y, float z) const
|
||||
{
|
||||
Vector3 Matrix::TransformPoint(float x, float y, float z) const {
|
||||
return Vector3{
|
||||
data[0].x * x + data[1].x * y + data[2].x * z + data[3].x,
|
||||
data[0].y * x + data[1].y * y + data[2].y * z + data[3].y,
|
||||
@@ -55,13 +48,11 @@ namespace dae {
|
||||
};
|
||||
}
|
||||
|
||||
Vector4 Matrix::TransformPoint(const Vector4& p) const
|
||||
{
|
||||
Vector4 Matrix::TransformPoint(const Vector4 &p) const {
|
||||
return TransformPoint(p.x, p.y, p.z, p.w);
|
||||
}
|
||||
|
||||
Vector4 Matrix::TransformPoint(float x, float y, float z, float w) const
|
||||
{
|
||||
Vector4 Matrix::TransformPoint(float x, float y, float z, float w) const {
|
||||
return Vector4{
|
||||
data[0].x * x + data[1].x * y + data[2].x * z + data[3].x,
|
||||
data[0].y * x + data[1].y * y + data[2].y * z + data[3].y,
|
||||
@@ -70,13 +61,10 @@ namespace dae {
|
||||
};
|
||||
}
|
||||
|
||||
const Matrix& Matrix::Transpose()
|
||||
{
|
||||
const Matrix &Matrix::Transpose() {
|
||||
Matrix result{};
|
||||
for (int r{ 0 }; r < 4; ++r)
|
||||
{
|
||||
for (int c{ 0 }; c < 4; ++c)
|
||||
{
|
||||
for (int r{0}; r < 4; ++r) {
|
||||
for (int c{0}; c < 4; ++c) {
|
||||
result[r][c] = data[c][r];
|
||||
}
|
||||
}
|
||||
@@ -89,8 +77,7 @@ namespace dae {
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Matrix& Matrix::Inverse()
|
||||
{
|
||||
const Matrix &Matrix::Inverse() {
|
||||
//Optimized Inverse as explained in FGED1 - used widely in other libraries too.
|
||||
const Vector3 &a = data[0];
|
||||
const Vector3 &b = data[1];
|
||||
@@ -111,7 +98,10 @@ namespace dae {
|
||||
assert((!AreEqual(det, 0.f)) && "ERROR: determinant is 0, there is no INVERSE!");
|
||||
float invDet = 1.f / det;
|
||||
|
||||
s *= invDet; t *= invDet; u *= invDet; v *= invDet;
|
||||
s *= invDet;
|
||||
t *= invDet;
|
||||
u *= invDet;
|
||||
v *= invDet;
|
||||
|
||||
Vector3 r0 = Vector3::Cross(b, v) + t * y;
|
||||
Vector3 r1 = Vector3::Cross(v, a) - t * x;
|
||||
@@ -121,79 +111,90 @@ namespace dae {
|
||||
data[0] = Vector4{r0.x, r1.x, r2.x, 0.f};
|
||||
data[1] = Vector4{r0.y, r1.y, r2.y, 0.f};
|
||||
data[2] = Vector4{r0.z, r1.z, r2.z, 0.f};
|
||||
data[3] = { { -Vector3::Dot(b, t)},{Vector3::Dot(a, t)},{-Vector3::Dot(d, s)},{Vector3::Dot(c, s)} };
|
||||
data[3] = {{-Vector3::Dot(b, t)},
|
||||
{Vector3::Dot(a, t)},
|
||||
{-Vector3::Dot(d, s)},
|
||||
{Vector3::Dot(c, s)}};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Matrix Matrix::Transpose(const Matrix& m)
|
||||
{
|
||||
Matrix Matrix::Transpose(const Matrix &m) {
|
||||
Matrix out{m};
|
||||
out.Transpose();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Matrix Matrix::Inverse(const Matrix& m)
|
||||
{
|
||||
Matrix Matrix::Inverse(const Matrix &m) {
|
||||
Matrix out{m};
|
||||
out.Inverse();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateLookAtLH(const Vector3& origin, const Vector3& forward, const Vector3& up)
|
||||
{
|
||||
Vector3 zAxis = forward.Normalized();
|
||||
Matrix Matrix::CreateLookAtLH(const Vector3 &origin, const Vector3 &forward, const Vector3 &up) {
|
||||
Vector3 zAxis = (forward - origin).Normalized();
|
||||
Vector3 xAxis = Vector3::Cross(up, zAxis).Normalized();
|
||||
Vector3 yAxis = Vector3::Cross(zAxis, xAxis);
|
||||
|
||||
return { xAxis, yAxis, zAxis, origin };
|
||||
}
|
||||
|
||||
Matrix Matrix::CreatePerspectiveFovLH(float fov, float aspect, float zn, float zf) {
|
||||
const float yScale = 1.f / tanf(fov / 2.f);
|
||||
const float xScale = yScale / aspect;
|
||||
|
||||
Vector3 yAxis = Vector3::Cross(zAxis, xAxis).Normalized();
|
||||
Vector3 trans =
|
||||
{
|
||||
-Vector3::Dot(xAxis, origin),
|
||||
-Vector3::Dot(yAxis, origin),
|
||||
-Vector3::Dot(zAxis, origin)
|
||||
};
|
||||
return {
|
||||
{ xScale, 0, 0, 0 },
|
||||
{ 0, yScale, 0, 0 },
|
||||
{ 0, 0, zf / (zf - zn), 1 },
|
||||
{ 0, 0, -zn * zf / (zf - zn), 0 }
|
||||
{xAxis.x, yAxis.x, zAxis.x},
|
||||
{xAxis.y, yAxis.y, zAxis.y},
|
||||
{xAxis.z, yAxis.z, zAxis.z},
|
||||
{trans.x, trans.y, trans.z}
|
||||
};
|
||||
}
|
||||
Vector3 Matrix::GetAxisX() const
|
||||
{
|
||||
|
||||
Matrix Matrix::CreatePerspectiveFovLH(float fovy, float aspect, float zn, float zf) {
|
||||
// const float yScale = 1.f / tanf(fovy / 2.f);
|
||||
// const float xScale = yScale / aspect;
|
||||
//
|
||||
// return {
|
||||
// {xScale, 0, 0, 0},
|
||||
// {0, yScale, 0, 0},
|
||||
// {0, 0, zf / (zf - zn), 1},
|
||||
// {0, 0, -zn * zf / (zf - zn), 0}
|
||||
// };
|
||||
|
||||
return Matrix(
|
||||
{ 1.f / (aspect * fovy), 0, 0, 0 },
|
||||
{ 0, 1.f / fovy, 0, 0 },
|
||||
{ 0, 0, (zf) / (zf - zn), 1 },
|
||||
{ 0, 0, -(zf * zn) / (zf - zn), 0 }
|
||||
);
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetAxisX() const {
|
||||
return data[0];
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetAxisY() const
|
||||
{
|
||||
Vector3 Matrix::GetAxisY() const {
|
||||
return data[1];
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetAxisZ() const
|
||||
{
|
||||
Vector3 Matrix::GetAxisZ() const {
|
||||
return data[2];
|
||||
}
|
||||
|
||||
Vector3 Matrix::GetTranslation() const
|
||||
{
|
||||
Vector3 Matrix::GetTranslation() const {
|
||||
return data[3];
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateTranslation(float x, float y, float z)
|
||||
{
|
||||
Matrix Matrix::CreateTranslation(float x, float y, float z) {
|
||||
return CreateTranslation({x, y, z});
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateTranslation(const Vector3& t)
|
||||
{
|
||||
Matrix Matrix::CreateTranslation(const Vector3 &t) {
|
||||
return {Vector3::UnitX, Vector3::UnitY, Vector3::UnitZ, t};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationX(float pitch)
|
||||
{
|
||||
Matrix Matrix::CreateRotationX(float pitch) {
|
||||
return {
|
||||
{1, 0, 0, 0},
|
||||
{0, cos(pitch), -sin(pitch), 0},
|
||||
@@ -202,8 +203,7 @@ namespace dae {
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationY(float yaw)
|
||||
{
|
||||
Matrix Matrix::CreateRotationY(float yaw) {
|
||||
return {
|
||||
{cos(yaw), 0, -sin(yaw), 0},
|
||||
{0, 1, 0, 0},
|
||||
@@ -212,8 +212,7 @@ namespace dae {
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotationZ(float roll)
|
||||
{
|
||||
Matrix Matrix::CreateRotationZ(float roll) {
|
||||
return {
|
||||
{cos(roll), sin(roll), 0, 0},
|
||||
{-sin(roll), cos(roll), 0, 0},
|
||||
@@ -222,48 +221,40 @@ namespace dae {
|
||||
};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotation(float pitch, float yaw, float roll)
|
||||
{
|
||||
Matrix Matrix::CreateRotation(float pitch, float yaw, float roll) {
|
||||
return CreateRotation({pitch, yaw, roll});
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateRotation(const Vector3& r)
|
||||
{
|
||||
Matrix Matrix::CreateRotation(const Vector3 &r) {
|
||||
return CreateRotationX(r[0]) * CreateRotationY(r[1]) * CreateRotationZ(r[2]);
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateScale(float sx, float sy, float sz)
|
||||
{
|
||||
Matrix Matrix::CreateScale(float sx, float sy, float sz) {
|
||||
return {{sx, 0, 0}, {0, sy, 0}, {0, 0, sz}, Vector3::Zero};
|
||||
}
|
||||
|
||||
Matrix Matrix::CreateScale(const Vector3& s)
|
||||
{
|
||||
Matrix Matrix::CreateScale(const Vector3 &s) {
|
||||
return CreateScale(s[0], s[1], s[2]);
|
||||
}
|
||||
|
||||
#pragma region Operator Overloads
|
||||
Vector4& Matrix::operator[](int index)
|
||||
{
|
||||
|
||||
Vector4 &Matrix::operator[](int index) {
|
||||
assert(index <= 3 && index >= 0);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
Vector4 Matrix::operator[](int index) const
|
||||
{
|
||||
Vector4 Matrix::operator[](int index) const {
|
||||
assert(index <= 3 && index >= 0);
|
||||
return data[index];
|
||||
}
|
||||
|
||||
Matrix Matrix::operator*(const Matrix& m) const
|
||||
{
|
||||
Matrix Matrix::operator*(const Matrix &m) const {
|
||||
Matrix result{};
|
||||
Matrix m_transposed = Transpose(m);
|
||||
|
||||
for (int r{ 0 }; r < 4; ++r)
|
||||
{
|
||||
for (int c{ 0 }; c < 4; ++c)
|
||||
{
|
||||
for (int r{0}; r < 4; ++r) {
|
||||
for (int c{0}; c < 4; ++c) {
|
||||
result[r][c] = Vector4::Dot(data[r], m_transposed[c]);
|
||||
}
|
||||
}
|
||||
@@ -271,15 +262,12 @@ namespace dae {
|
||||
return result;
|
||||
}
|
||||
|
||||
const Matrix& Matrix::operator*=(const Matrix& m)
|
||||
{
|
||||
const Matrix &Matrix::operator*=(const Matrix &m) {
|
||||
Matrix copy{*this};
|
||||
Matrix m_transposed = Transpose(m);
|
||||
|
||||
for (int r{ 0 }; r < 4; ++r)
|
||||
{
|
||||
for (int c{ 0 }; c < 4; ++c)
|
||||
{
|
||||
for (int r{0}; r < 4; ++r) {
|
||||
for (int c{0}; c < 4; ++c) {
|
||||
data[r][c] = Vector4::Dot(copy[r], m_transposed[c]);
|
||||
}
|
||||
}
|
||||
@@ -287,8 +275,7 @@ namespace dae {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Matrix::operator==(const Matrix& m) const
|
||||
{
|
||||
bool Matrix::operator==(const Matrix &m) const {
|
||||
return data[0] == m.data[0]
|
||||
&& data[1] == m.data[1]
|
||||
&& data[2] == m.data[2]
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
//External includes
|
||||
#include <iostream>
|
||||
#include <SDL.h>
|
||||
#include <array>
|
||||
#include "SDL_surface.h"
|
||||
|
||||
//Project includes
|
||||
#include "Renderer.h"
|
||||
#include "Maths.h"
|
||||
#include "HitTest.h"
|
||||
#include "utils.h"
|
||||
|
||||
using namespace dae;
|
||||
|
||||
@@ -21,13 +24,16 @@ Renderer::Renderer(SDL_Window *pWindow) : m_pWindow(pWindow) {
|
||||
m_pDepthBufferPixels = new float[m_Width * m_Height];
|
||||
|
||||
//Initialize Camera
|
||||
m_Camera.Initialize(60.f, {.0f, .0f, -10.f});
|
||||
|
||||
//Initialize Camera
|
||||
m_Camera.Initialize(60.f, {.0f, .0f, -10.f});
|
||||
m_aspectRatio = static_cast<float>(m_Width) / static_cast<float>(m_Height);
|
||||
m_Camera.Initialize(45.f, {.0f, 5.0f, -64.f}, m_aspectRatio);
|
||||
|
||||
m_pTexture = Texture::LoadFromFile("./Resources/uv_grid_2.png");
|
||||
m_currentDiffuse = Texture::LoadFromFile("./Resources/vehicle_diffuse.png");
|
||||
m_currentGloss = Texture::LoadFromFile("./Resources/vehicle_gloss.png");
|
||||
m_currentNormal = Texture::LoadFromFile("./Resources/vehicle_normal.png");
|
||||
m_currentSpecular = Texture::LoadFromFile("./Resources/vehicle_specular.png");
|
||||
|
||||
Utils::ParseOBJ("./Resources/vehicle.obj", m_mesh.vertices, m_mesh.indices, false);
|
||||
m_worldMeshes.push_back(m_mesh);
|
||||
}
|
||||
|
||||
Renderer::~Renderer() {
|
||||
@@ -36,6 +42,11 @@ Renderer::~Renderer() {
|
||||
|
||||
void Renderer::Update(Timer *pTimer) {
|
||||
m_Camera.Update(pTimer);
|
||||
|
||||
//Rotate the mesh
|
||||
if(m_isRotating){
|
||||
m_worldMeshes[0].worldMatrix = Matrix::CreateRotationY(SDL_GetTicks() / 1000.f);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::Render() {
|
||||
@@ -54,10 +65,11 @@ void Renderer::Render() {
|
||||
constexpr int numVerticies = 3;
|
||||
|
||||
std::vector<Vertex> verticiesScreenSpace{};
|
||||
// VertexTransformationFunction(m_verticiesWorld, verticiesScreenSpace);
|
||||
|
||||
for (const Mesh ¤tMesh: m_meshesWorldStrip) {
|
||||
VertexTransformationFunction(currentMesh.vertices, verticiesScreenSpace);
|
||||
for (const Mesh ¤tMesh: m_worldMeshes) {
|
||||
|
||||
const Matrix worldViewProjectionMatrix{ currentMesh.worldMatrix * m_Camera.viewMatrix * m_Camera.ProjectionMatrix };
|
||||
VertexTransformationFunction(worldViewProjectionMatrix, currentMesh, currentMesh.vertices, verticiesScreenSpace);
|
||||
|
||||
int numTriangles{};
|
||||
|
||||
@@ -97,6 +109,10 @@ void Renderer::Render() {
|
||||
}
|
||||
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))};
|
||||
@@ -127,44 +143,31 @@ void Renderer::Render() {
|
||||
|
||||
Vector3 P{static_cast<float>(px) + 0.5f, static_cast<float>(py) + 0.5f, 1.f};
|
||||
|
||||
const Vector3 cross0{Vector3::Cross(vertex2.position - vertex1.position, P - vertex1.position)};
|
||||
if (cross0.z < 0) {
|
||||
continue;
|
||||
}
|
||||
const Vector3 cross1{Vector3::Cross(vertex0.position - vertex2.position, P - vertex2.position)};
|
||||
if (cross1.z < 0) {
|
||||
continue;
|
||||
}
|
||||
const Vector3 cross2{Vector3::Cross(vertex1.position - vertex0.position, P - vertex0.position)};
|
||||
if (cross2.z < 0) {
|
||||
auto sample{ HitTest::TriangleHitTest(P, vertex0, vertex1, vertex2) };
|
||||
|
||||
if (!sample.has_value()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const int depthBufferIndex{px + (py * m_Width)};
|
||||
const Vector3 fragPos{ static_cast<float>(px) + 0.5f, static_cast<float>(py) + 0.5f, 1.f };
|
||||
|
||||
float totalWeight{cross0.z + cross1.z + cross2.z};
|
||||
Vector3 weights{
|
||||
cross0.z / totalWeight,
|
||||
cross1.z / totalWeight,
|
||||
cross2.z / totalWeight,
|
||||
};
|
||||
int depthBufferIndex{ px + (py * m_Width) };
|
||||
|
||||
const float currentDepth =
|
||||
1 / (weights.x / vertex0.position.z +
|
||||
weights.y / vertex1.position.z +
|
||||
weights.z / vertex2.position.z);
|
||||
float min{.985f};
|
||||
float max{1.f};
|
||||
float depthBuffer{(sample.value().depth - min) * (max - min)};
|
||||
float currentDepth = sample.value().depth;
|
||||
|
||||
const Vector2 UvCoords =
|
||||
vertex0.uv * currentDepth * weights.x / vertex0.position.z +
|
||||
vertex1.uv * currentDepth * weights.y / vertex1.position.z +
|
||||
vertex2.uv * currentDepth * weights.z / vertex2.position.z;
|
||||
|
||||
|
||||
if (m_pDepthBufferPixels[depthBufferIndex] >= currentDepth) {
|
||||
if (m_pDepthBufferPixels[depthBufferIndex] > currentDepth) {
|
||||
m_pDepthBufferPixels[depthBufferIndex] = currentDepth;
|
||||
|
||||
//Update Color in Buffer
|
||||
finalColor = m_pTexture->Sample(UvCoords);
|
||||
if (m_isDepthBuffer) {
|
||||
finalColor = ColorRGB{depthBuffer, depthBuffer, depthBuffer};
|
||||
} else {
|
||||
// finalColor = m_pTexture->Sample(UvCoords);
|
||||
finalColor = shadePixel(sample.value());
|
||||
}
|
||||
|
||||
finalColor.MaxToOne();
|
||||
|
||||
m_pBackBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
|
||||
@@ -174,28 +177,14 @@ void Renderer::Render() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int x, y{0};
|
||||
//For loop over all the pixels
|
||||
for (int px{}; px < 100; ++px) {
|
||||
for (int py{}; py < 100; ++py) {
|
||||
//Get the pixel position
|
||||
x = px;
|
||||
y = py;
|
||||
|
||||
ColorRGB test = m_pTexture->Sample(Vector2{static_cast<float>(px) / 100, static_cast<float>(py) / 100});
|
||||
m_pBackBufferPixels[x + (y * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
|
||||
static_cast<uint8_t>(test.r * 255),
|
||||
static_cast<uint8_t>(test.g * 255),
|
||||
static_cast<uint8_t>(test.b * 255));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//RENDER LOGIC
|
||||
|
||||
@@ -205,20 +194,117 @@ void Renderer::Render() {
|
||||
SDL_UpdateWindowSurface(m_pWindow);
|
||||
}
|
||||
|
||||
void Renderer::VertexTransformationFunction(const std::vector<Vertex> &vertices_in,
|
||||
void Renderer::VertexTransformationFunction(const Matrix& WorldViewProjectionMatrix, const Mesh& mesh, const std::vector<Vertex> &vertices_in,
|
||||
std::vector<Vertex> &vertices_out) const {
|
||||
for (const Vertex &vert: vertices_in) {
|
||||
Vector3 vertPos{m_Camera.invViewMatrix.TransformPoint(vert.position)};
|
||||
// vertices_out.clear();
|
||||
for (const Vertex& vert : vertices_in)
|
||||
{
|
||||
Vertex vertex_out{};
|
||||
|
||||
vertPos.x = (vertPos.x / vertPos.z) / (m_aspectRatio * m_Camera.fov);
|
||||
vertPos.y = (vertPos.y / vertPos.z) / m_Camera.fov;
|
||||
Vector4 vertPos{ WorldViewProjectionMatrix.TransformPoint({vert.position.GetXYZ(), 1}) };
|
||||
|
||||
vertPos.x = (vertPos.x + 1) / 2 * static_cast<float>(m_Width);
|
||||
vertPos.y = (1 - vertPos.y) / 2 * static_cast<float>(m_Height);
|
||||
vertices_out.push_back(Vertex{vertPos, vert.color, vert.uv});
|
||||
const Vector3 normal{ mesh.worldMatrix.TransformVector(vert.normal) };
|
||||
const Vector3 tangent{ mesh.worldMatrix.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.color = vert.color;
|
||||
vertex_out.uv = vert.uv;
|
||||
vertex_out.normal = normal;
|
||||
vertex_out.tangent = tangent;
|
||||
vertex_out.viewDir = WorldViewProjectionMatrix.TransformVector(vert.viewDir);
|
||||
vertex_out.valid = isValid;
|
||||
|
||||
vertices_out.push_back(vertex_out);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Renderer::SaveBufferToImage() const {
|
||||
return SDL_SaveBMP(m_pBackBuffer, "Rasterizer_ColorBuffer.bmp");
|
||||
}
|
||||
|
||||
ColorRGB Renderer::shadePixel(const Sample &sample) {
|
||||
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{ m_currentNormal->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{ m_currentDiffuse->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 *= m_currentGloss->Sample(sample.uv).r;
|
||||
shininess *= m_currentSpecular->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;
|
||||
}
|
||||
|
||||
@@ -11,8 +11,16 @@
|
||||
struct SDL_Window;
|
||||
struct SDL_Surface;
|
||||
|
||||
|
||||
namespace dae {
|
||||
|
||||
enum class ShadeMode{
|
||||
ObservedArea,
|
||||
Diffuse,
|
||||
Specular,
|
||||
Combined
|
||||
};
|
||||
|
||||
struct Mesh;
|
||||
|
||||
class Timer;
|
||||
@@ -40,7 +48,48 @@ namespace dae {
|
||||
bool SaveBufferToImage() const;
|
||||
|
||||
void
|
||||
VertexTransformationFunction(const std::vector<Vertex> &vertices_in, std::vector<Vertex> &vertices_out) const;
|
||||
VertexTransformationFunction(const Matrix& WorldViewProjectionMatrix, const Mesh& mesh, const std::vector<Vertex> &vertices_in, std::vector<Vertex> &vertices_out) const;
|
||||
|
||||
ColorRGB shadePixel(const Sample& sample);
|
||||
|
||||
void SwitchDepthBuffer(){
|
||||
m_isDepthBuffer = !m_isDepthBuffer;
|
||||
}
|
||||
|
||||
void SetShadeMode(ShadeMode mode) {
|
||||
m_ShadeMode = mode;
|
||||
}
|
||||
|
||||
void ToggleRotation(){
|
||||
m_isRotating = !m_isRotating;
|
||||
std::cout << "Rotation: " << m_isRotating << std::endl;
|
||||
}
|
||||
|
||||
void ToggleNormals(){
|
||||
m_useNormals = !m_useNormals;
|
||||
std::cout << "Use Normals: " << m_useNormals << std::endl;
|
||||
}
|
||||
|
||||
void 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;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SDL_Window *m_pWindow{};
|
||||
@@ -56,83 +105,22 @@ namespace dae {
|
||||
|
||||
float m_aspectRatio{};
|
||||
|
||||
Texture* m_pTexture{ nullptr };
|
||||
//
|
||||
// std::vector<Vertex> m_verticiesWorld{
|
||||
// //Triangle 0
|
||||
// {{0.f,2.f,0.f}, {1,0,0}},
|
||||
// {{1.5f,-1.f,0.f}, {1,0,0}},
|
||||
// {{-1.5f,-1.f,0.f}, {1,0,0}},
|
||||
//
|
||||
// //Triangle 1
|
||||
// {{0.f,4.f,2.f}, {1,0,0}},
|
||||
// {{3.f,-2.f,2.f}, {0,1,0}},
|
||||
// {{-3.f,-2.f,2.f}, {0,0,1}}
|
||||
// };
|
||||
Texture* m_currentDiffuse{ nullptr };
|
||||
Texture* m_currentGloss{ nullptr };
|
||||
Texture* m_currentNormal{ nullptr };
|
||||
Texture* m_currentSpecular{ nullptr };
|
||||
|
||||
std::vector<Mesh> m_meshesWorldList
|
||||
{
|
||||
Mesh
|
||||
{
|
||||
{
|
||||
Vertex{ {-3, 3, -2 }, { 1, 1, 1 }, { 0.0f, 0.0f } },
|
||||
Vertex{ { 0, 3, -2 }, { 1, 1, 1 }, { 0.5f, 0.0f } },
|
||||
Vertex{ { 3, 3, -2 }, { 1, 1, 1 }, { 1.0f, 0.0f } },
|
||||
Vertex{ {-3, 0, -2 }, { 1, 1, 1 }, { 0.0f, 0.5f } },
|
||||
Vertex{ { 0, 0, -2 }, { 1, 1, 1 }, { 0.5f, 0.5f } },
|
||||
Vertex{ { 3, 0, -2 }, { 1, 1, 1 }, { 1.0f, 0.5f } },
|
||||
Vertex{ {-3, -3, -2 }, { 1, 1, 1 }, { 0.0f, 1.0f } },
|
||||
Vertex{ { 0, -3, -2 }, { 1, 1, 1 }, { 0.5f, 1.0f } },
|
||||
Vertex{ { 3, -3, -2 }, { 1, 1, 1 }, { 1.0f, 1.0f } }
|
||||
},
|
||||
{
|
||||
3, 0, 1, 1, 4, 3, 4, 1 ,2,
|
||||
2, 5, 4, 6, 3, 4, 4, 7, 6,
|
||||
7, 4, 5, 5, 8, 7
|
||||
},
|
||||
PrimitiveTopology::TriangleList
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Mesh> m_meshesWorldStrip
|
||||
{
|
||||
Mesh
|
||||
{
|
||||
std::vector<Vertex>{
|
||||
{{-3, 3, -2}, {colors::White}, {0,0} },
|
||||
{{0, 3, -2}, {colors::Red}, {0.5,0}},
|
||||
{{3, 3, -2}, {colors::Blue}, {1,0}},
|
||||
{{-3, 0, -2}, {colors::Red}, {0,0.5}},
|
||||
{{0, 0, -2}, {colors::Yellow}, {0.5, 0.5}},
|
||||
{{3, 0, -2}, {colors::White}, {1, 0.5}},
|
||||
{{-3, -3, -2}, {colors::White}, {0,1}},
|
||||
{{0, -3, -2}, {colors::White}, {0.5,1}},
|
||||
{{3, -3, -2}, {colors::White}, {1,1}},
|
||||
},
|
||||
std::vector<uint32_t>{
|
||||
3, 0, 4, 1, 5, 2,
|
||||
2, 6,
|
||||
6, 3, 7, 4, 8, 5,
|
||||
},
|
||||
PrimitiveTopology::TriangleStrip,
|
||||
}
|
||||
};
|
||||
//square
|
||||
std::vector<Mesh> testMesh{
|
||||
Mesh{
|
||||
std::vector<Vertex>{
|
||||
{{-1, 1, 0}, {colors::White}, {0, 0}},
|
||||
{{1, 1, 0}, {colors::White}, {1, 0}},
|
||||
{{-1, -1, 0}, {colors::White}, {0, 1}},
|
||||
{{1, -1, 0}, {colors::White}, {1, 1}},
|
||||
},
|
||||
std::vector<uint32_t>{
|
||||
0, 1, 2, 1, 3, 2
|
||||
},
|
||||
PrimitiveTopology::TriangleList
|
||||
}
|
||||
};
|
||||
// std::vector<Vertex> m_verticies_screenSpace{};
|
||||
ShadeMode m_ShadeMode{ ShadeMode::Combined };
|
||||
bool m_isRotating{ true };
|
||||
bool m_useNormals{ true };
|
||||
|
||||
Mesh m_mesh{};
|
||||
|
||||
bool m_isDepthBuffer{ false };
|
||||
|
||||
|
||||
std::vector<Mesh> m_worldMeshes{};
|
||||
|
||||
float* m_pDepthBufferPixels{};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "Maths.h"
|
||||
#include "DataTypes.h"
|
||||
|
||||
#define DISABLE_OBJ
|
||||
//#define DISABLE_OBJ
|
||||
|
||||
namespace dae
|
||||
{
|
||||
@@ -84,7 +84,7 @@ namespace dae
|
||||
{
|
||||
// OBJ format uses 1-based arrays
|
||||
file >> iPosition;
|
||||
vertex.position = positions[iPosition - 1];
|
||||
vertex.position = positions[iPosition - 1].ToVector4();
|
||||
|
||||
if ('/' == file.peek())//is next in buffer == '/' ?
|
||||
{
|
||||
|
||||
@@ -6,10 +6,10 @@ namespace dae
|
||||
struct Vector3;
|
||||
struct Vector4
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
float w;
|
||||
float x{};
|
||||
float y{};
|
||||
float z{};
|
||||
float w{};
|
||||
|
||||
Vector4() = default;
|
||||
Vector4(float _x, float _y, float _z, float _w);
|
||||
@@ -20,8 +20,8 @@ namespace dae
|
||||
float Normalize();
|
||||
Vector4 Normalized() const;
|
||||
|
||||
Vector2 GetXY() const;
|
||||
Vector3 GetXYZ() const;
|
||||
[[nodiscard]] Vector2 GetXY() const;
|
||||
[[nodiscard]] Vector3 GetXYZ() const;
|
||||
|
||||
static float Dot(const Vector4& v1, const Vector4& v2);
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#ifdef ENABLE_VLD
|
||||
#include "vld.h"
|
||||
#endif
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_surface.h"
|
||||
|
||||
#undef main
|
||||
|
||||
//Standard includes
|
||||
@@ -15,14 +17,12 @@
|
||||
|
||||
using namespace dae;
|
||||
|
||||
void ShutDown(SDL_Window* pWindow)
|
||||
{
|
||||
void ShutDown(SDL_Window *pWindow) {
|
||||
SDL_DestroyWindow(pWindow);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
int main(int argc, char* args[])
|
||||
{
|
||||
int main(int argc, char *args[]) {
|
||||
//Unreferenced parameters
|
||||
(void) argc;
|
||||
(void) args;
|
||||
@@ -34,7 +34,7 @@ int main(int argc, char* args[])
|
||||
const uint32_t height = 480;
|
||||
|
||||
SDL_Window *pWindow = SDL_CreateWindow(
|
||||
"Rasterizer - **Insert Name**",
|
||||
"Rasterizer - Bram Verhulst",
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
width, height, 0);
|
||||
@@ -55,14 +55,11 @@ int main(int argc, char* args[])
|
||||
float printTimer = 0.f;
|
||||
bool isLooping = true;
|
||||
bool takeScreenshot = false;
|
||||
while (isLooping)
|
||||
{
|
||||
while (isLooping) {
|
||||
//--------- Get input events ---------
|
||||
SDL_Event e;
|
||||
while (SDL_PollEvent(&e))
|
||||
{
|
||||
switch (e.type)
|
||||
{
|
||||
while (SDL_PollEvent(&e)) {
|
||||
switch (e.type) {
|
||||
case SDL_QUIT:
|
||||
isLooping = false;
|
||||
break;
|
||||
@@ -70,6 +67,21 @@ int main(int argc, char* args[])
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_X)
|
||||
takeScreenshot = true;
|
||||
break;
|
||||
case SDL_KEYDOWN: {
|
||||
auto key = e.key.keysym.scancode;
|
||||
if (key == SDL_SCANCODE_F4) {
|
||||
pRenderer->SwitchDepthBuffer();
|
||||
}
|
||||
if (key == SDL_SCANCODE_F5) {
|
||||
pRenderer->ToggleRotation();
|
||||
}
|
||||
if (key == SDL_SCANCODE_F6) {
|
||||
pRenderer->ToggleNormals();
|
||||
}
|
||||
if (key == SDL_SCANCODE_F7) {
|
||||
pRenderer->CycleRenderingMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,15 +94,13 @@ int main(int argc, char* args[])
|
||||
//--------- Timer ---------
|
||||
pTimer->Update();
|
||||
printTimer += pTimer->GetElapsed();
|
||||
if (printTimer >= 1.f)
|
||||
{
|
||||
if (printTimer >= 1.f) {
|
||||
printTimer = 0.f;
|
||||
std::cout << "dFPS: " << pTimer->GetdFPS() << std::endl;
|
||||
}
|
||||
|
||||
//Save screenshot after full render
|
||||
if (takeScreenshot)
|
||||
{
|
||||
if (takeScreenshot) {
|
||||
if (!pRenderer->SaveBufferToImage())
|
||||
std::cout << "Screenshot saved!" << std::endl;
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user