Add Instanced Rendering / 2 more scenes
This commit is contained in:
@@ -192,3 +192,29 @@ dae::Matrix dae::Camera::GetViewProjectionMatrix() const {
|
||||
const dae::Vector3 &dae::Camera::GetPosition() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
const dae::Vector3 dae::Camera::GetRotation() const {
|
||||
return {totalPitch, totalYaw, 0.f};
|
||||
}
|
||||
|
||||
void dae::Camera::SetPosition(const dae::Vector3 &position) {
|
||||
origin = position;
|
||||
|
||||
CalculateViewMatrix();
|
||||
CalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
void dae::Camera::SetRotation(const dae::Vector3 &rotation) {
|
||||
totalPitch = rotation.x;
|
||||
totalYaw = rotation.y;
|
||||
|
||||
const Matrix yawMatrix{Matrix::CreateRotationY(totalYaw)};
|
||||
const Matrix pitchMatrix{Matrix::CreateRotationX(totalPitch)};
|
||||
|
||||
const Matrix finalRotation{pitchMatrix * yawMatrix};
|
||||
forward = finalRotation.TransformVector(Vector3::UnitZ);
|
||||
forward.Normalize();
|
||||
|
||||
CalculateViewMatrix();
|
||||
CalculateProjectionMatrix();
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ namespace dae {
|
||||
Matrix GetViewProjectionMatrix() const;
|
||||
|
||||
const Vector3 &GetPosition();
|
||||
void SetPosition(const Vector3& position);
|
||||
|
||||
const Vector3 GetRotation() const;
|
||||
void SetRotation(const Vector3& rotation);
|
||||
|
||||
private:
|
||||
Vector3 origin{};
|
||||
|
||||
228
project/src/InstancedMesh.cpp
Normal file
228
project/src/InstancedMesh.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
#include <cassert>
|
||||
#include "InstancedMesh.h"
|
||||
|
||||
InstancedMesh::InstancedMesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices,
|
||||
std::shared_ptr<Material> material, BaseEffect *effectPtr, const std::vector<InstancedData> &instanceData)
|
||||
: m_EffectPtr(effectPtr),
|
||||
m_InputLayoutPtr(nullptr),
|
||||
m_VertexBufferPtr(nullptr),
|
||||
m_IndexBufferPtr(nullptr),
|
||||
m_InstanceBufferPtr(nullptr),
|
||||
m_VerticesIn(verticesIn),
|
||||
m_Indices(indices),
|
||||
m_InstancedData(instanceData),
|
||||
m_InstanceCount(static_cast<UINT>(instanceData.size())),
|
||||
m_IndicesCount(static_cast<UINT>(m_Indices.size())),
|
||||
m_Material(std::move(material)) {
|
||||
HRESULT result;
|
||||
D3D11_BUFFER_DESC bufferDesc{};
|
||||
D3D11_SUBRESOURCE_DATA subresourceData{};
|
||||
|
||||
m_EffectPtr->SetMaterial(m_Material.get());
|
||||
|
||||
|
||||
//Create vertex layout
|
||||
static constexpr uint32_t vertexElementCount{9}; // 4 for vertex data + 4 for world matrix + 1 for instance color
|
||||
D3D11_INPUT_ELEMENT_DESC vertexDesc[vertexElementCount]{};
|
||||
|
||||
// Vertex data
|
||||
vertexDesc[0].SemanticName = "POSITION";
|
||||
vertexDesc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
vertexDesc[0].AlignedByteOffset = 0;
|
||||
vertexDesc[0].InputSlot = 0;
|
||||
vertexDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
|
||||
vertexDesc[1].SemanticName = "TEXCOORD";
|
||||
vertexDesc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
|
||||
vertexDesc[1].AlignedByteOffset = offsetof(VertexIn, uv);
|
||||
vertexDesc[1].InputSlot = 0;
|
||||
vertexDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
|
||||
vertexDesc[2].SemanticName = "NORMAL";
|
||||
vertexDesc[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
vertexDesc[2].AlignedByteOffset = offsetof(VertexIn, normal);
|
||||
vertexDesc[2].InputSlot = 0;
|
||||
vertexDesc[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
|
||||
vertexDesc[3].SemanticName = "TANGENT";
|
||||
vertexDesc[3].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
vertexDesc[3].AlignedByteOffset = offsetof(VertexIn, tangent);
|
||||
vertexDesc[3].InputSlot = 0;
|
||||
vertexDesc[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
|
||||
|
||||
// Instance world matrix (split into four float4 components)
|
||||
vertexDesc[4].SemanticName = "INSTANCEWORLD";
|
||||
vertexDesc[4].SemanticIndex = 0; // First row of the matrix
|
||||
vertexDesc[4].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
vertexDesc[4].AlignedByteOffset = 0;
|
||||
vertexDesc[4].InputSlot = 1;
|
||||
vertexDesc[4].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
|
||||
vertexDesc[4].InstanceDataStepRate = 1;
|
||||
|
||||
vertexDesc[5].SemanticName = "INSTANCEWORLD";
|
||||
vertexDesc[5].SemanticIndex = 1; // Second row of the matrix
|
||||
vertexDesc[5].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
vertexDesc[5].AlignedByteOffset = 16; // 4 floats * 4 bytes per float
|
||||
vertexDesc[5].InputSlot = 1;
|
||||
vertexDesc[5].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
|
||||
vertexDesc[5].InstanceDataStepRate = 1;
|
||||
|
||||
vertexDesc[6].SemanticName = "INSTANCEWORLD";
|
||||
vertexDesc[6].SemanticIndex = 2; // Third row of the matrix
|
||||
vertexDesc[6].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
vertexDesc[6].AlignedByteOffset = 32;
|
||||
vertexDesc[6].InputSlot = 1;
|
||||
vertexDesc[6].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
|
||||
vertexDesc[6].InstanceDataStepRate = 1;
|
||||
|
||||
vertexDesc[7].SemanticName = "INSTANCEWORLD";
|
||||
vertexDesc[7].SemanticIndex = 3; // Fourth row of the matrix
|
||||
vertexDesc[7].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
vertexDesc[7].AlignedByteOffset = 48;
|
||||
vertexDesc[7].InputSlot = 1;
|
||||
vertexDesc[7].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
|
||||
vertexDesc[7].InstanceDataStepRate = 1;
|
||||
|
||||
// Instance color
|
||||
vertexDesc[8].SemanticName = "INSTANCECOLOR";
|
||||
vertexDesc[8].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
vertexDesc[8].AlignedByteOffset = 64; // After the matrix
|
||||
vertexDesc[8].InputSlot = 1;
|
||||
vertexDesc[8].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
|
||||
vertexDesc[8].InstanceDataStepRate = 1;
|
||||
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC; // Allow updates
|
||||
bufferDesc.ByteWidth = sizeof(InstancedData) * m_InstanceCount; // Correct buffer size calculation
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
subresourceData.pSysMem = m_InstancedData.data();
|
||||
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_InstanceBufferPtr);
|
||||
assert(result == S_OK && "Creating instance buffer failed");
|
||||
|
||||
//Create input layout
|
||||
D3DX11_PASS_DESC passDesc{};
|
||||
ID3DX11EffectTechnique *techniquePtr = m_EffectPtr->GetTechniquePtr();
|
||||
techniquePtr->GetPassByIndex(0)->GetDesc(&passDesc);
|
||||
|
||||
result = devicePtr->CreateInputLayout(
|
||||
vertexDesc,
|
||||
vertexElementCount,
|
||||
passDesc.pIAInputSignature,
|
||||
passDesc.IAInputSignatureSize,
|
||||
&m_InputLayoutPtr);
|
||||
|
||||
assert(result == S_OK && "Creating input layout failed");
|
||||
|
||||
//Create vertex buffer
|
||||
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
bufferDesc.ByteWidth = sizeof(VertexIn) * static_cast<uint32_t>(verticesIn.size());
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
subresourceData.pSysMem = verticesIn.data();
|
||||
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_VertexBufferPtr);
|
||||
|
||||
assert(result == S_OK && "Creating vertex buffer failed");
|
||||
|
||||
//Create index buffer
|
||||
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
||||
bufferDesc.ByteWidth = sizeof(uint32_t) * m_IndicesCount;
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
subresourceData.pSysMem = m_Indices.data();
|
||||
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_IndexBufferPtr);
|
||||
|
||||
assert(result == S_OK && "Creating index buffer failed");
|
||||
}
|
||||
|
||||
InstancedMesh::~InstancedMesh() {
|
||||
m_InputLayoutPtr->Release();
|
||||
m_InputLayoutPtr = nullptr;
|
||||
|
||||
m_VertexBufferPtr->Release();
|
||||
m_VertexBufferPtr = nullptr;
|
||||
|
||||
m_IndexBufferPtr->Release();
|
||||
m_IndexBufferPtr = nullptr;
|
||||
|
||||
if (m_InstanceBufferPtr) {
|
||||
m_InstanceBufferPtr->Release();
|
||||
m_InstanceBufferPtr = nullptr;
|
||||
}
|
||||
|
||||
delete m_EffectPtr;
|
||||
m_EffectPtr = nullptr;
|
||||
|
||||
m_Material.reset();
|
||||
|
||||
m_InstancedData.clear();
|
||||
|
||||
m_VerticesIn.clear();
|
||||
}
|
||||
|
||||
void InstancedMesh::Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldViewProj) const {
|
||||
m_EffectPtr->SetWorldViewProjMatrix(worldViewProj);
|
||||
|
||||
deviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
deviceContextPtr->IASetInputLayout(m_InputLayoutPtr);
|
||||
|
||||
constexpr UINT vertexStride = sizeof(VertexIn);
|
||||
constexpr UINT vertexOffset = 0;
|
||||
|
||||
constexpr UINT instanceStride = sizeof(InstancedData);
|
||||
constexpr UINT instanceOffset = 0;
|
||||
|
||||
ID3D11Buffer *buffers[] = {m_VertexBufferPtr, m_InstanceBufferPtr};
|
||||
UINT strides[] = {vertexStride, instanceStride};
|
||||
UINT offsets[] = {vertexOffset, instanceOffset};
|
||||
|
||||
deviceContextPtr->IASetVertexBuffers(0, 2, buffers, strides, offsets);
|
||||
|
||||
deviceContextPtr->IASetIndexBuffer(m_IndexBufferPtr, DXGI_FORMAT_R32_UINT, 0);
|
||||
|
||||
// Draw using instancing
|
||||
D3DX11_TECHNIQUE_DESC techniqueDesc{};
|
||||
m_EffectPtr->GetTechniquePtr()->GetDesc(&techniqueDesc);
|
||||
for (UINT p{}; p < techniqueDesc.Passes; p++) {
|
||||
m_EffectPtr->GetTechniquePtr()->GetPassByIndex(p)->Apply(0, deviceContextPtr);
|
||||
deviceContextPtr->DrawIndexedInstanced(m_IndicesCount, m_InstanceCount, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void InstancedMesh::UpdateInstanceData(ID3D11DeviceContext *deviceContextPtr, const std::vector<InstancedData> &instanceData) {
|
||||
assert(instanceData.size() <= m_InstanceCount && "Instance data exceeds buffer size");
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource{};
|
||||
|
||||
HRESULT result = deviceContextPtr->Map(m_InstanceBufferPtr, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
assert(result == S_OK && "Mapping instance buffer failed");
|
||||
|
||||
assert(mappedResource.pData != nullptr && "Mapped resource data is null");
|
||||
|
||||
if (!instanceData.empty()) {
|
||||
// Ensure that the data fits in the buffer
|
||||
std::memcpy(mappedResource.pData, instanceData.data(), sizeof(InstancedData) * instanceData.size());
|
||||
}
|
||||
|
||||
deviceContextPtr->Unmap(m_InstanceBufferPtr, 0);
|
||||
}
|
||||
|
||||
void InstancedMesh::SetCameraPos(const Vector3 &pos) const {
|
||||
m_EffectPtr->SetCameraPos(pos);
|
||||
}
|
||||
|
||||
void InstancedMesh::SetWorldMatrix(const Matrix &matrix) {
|
||||
m_WorldMatrix = matrix;
|
||||
}
|
||||
|
||||
Material *InstancedMesh::GetMaterial() const { return m_Material.get(); }
|
||||
|
||||
Matrix InstancedMesh::GetWorldMatrix() const { return m_WorldMatrix; }
|
||||
|
||||
void InstancedMesh::SetMaterial(Material *pMaterial) {
|
||||
m_Material.reset(pMaterial);
|
||||
m_EffectPtr->SetMaterial(pMaterial);
|
||||
}
|
||||
66
project/src/InstancedMesh.h
Normal file
66
project/src/InstancedMesh.h
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef GP1_DIRECTX_INSTANCEDMESH_H
|
||||
#define GP1_DIRECTX_INSTANCEDMESH_H
|
||||
|
||||
#include "Texture.h"
|
||||
#include "Effects/BaseEffect.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
struct alignas(16) InstancedData {
|
||||
Matrix worldMatrix;
|
||||
Vector4 color;
|
||||
};
|
||||
|
||||
class InstancedMesh {
|
||||
public:
|
||||
InstancedMesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices,
|
||||
std::shared_ptr<Material> material, BaseEffect* effectPtr, const std::vector<InstancedData>& instanceData);
|
||||
|
||||
~InstancedMesh();
|
||||
|
||||
void Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldViewProj) const;
|
||||
|
||||
void SetCameraPos(const Vector3 &pos) const;
|
||||
|
||||
Matrix GetWorldMatrix() const;
|
||||
|
||||
|
||||
Material* GetMaterial() const;
|
||||
|
||||
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 UpdateInstanceData(ID3D11DeviceContext* deviceContextPtr, const std::vector<InstancedData>& instanceData);
|
||||
|
||||
private:
|
||||
BaseEffect *m_EffectPtr;
|
||||
|
||||
Matrix m_WorldMatrix{};
|
||||
|
||||
ID3D11InputLayout *m_InputLayoutPtr;
|
||||
ID3D11Buffer *m_VertexBufferPtr;
|
||||
ID3D11Buffer *m_IndexBufferPtr;
|
||||
|
||||
ID3D11Buffer* m_InstanceBufferPtr;
|
||||
std::vector<InstancedData> m_InstancedData;
|
||||
UINT m_InstanceCount;
|
||||
|
||||
std::vector<VertexIn> m_VerticesIn;
|
||||
std::vector<uint32_t> m_Indices;
|
||||
UINT m_IndicesCount;
|
||||
|
||||
std::shared_ptr<Material> m_Material{};
|
||||
|
||||
PrimitiveTopology m_PrimitiveTopology{PrimitiveTopology::TriangleList};
|
||||
};
|
||||
|
||||
|
||||
#endif //GP1_DIRECTX_INSTANCEDMESH_H
|
||||
@@ -8,7 +8,8 @@
|
||||
#include "HitTest.h"
|
||||
#include "Scenes/MainScene.h"
|
||||
#include "Scenes/DioramaScene.h"
|
||||
|
||||
#include "Scenes/InstancedScene.h"
|
||||
#include "Scenes/PlanetScene.h"
|
||||
|
||||
|
||||
namespace dae {
|
||||
@@ -27,12 +28,20 @@ namespace dae {
|
||||
std::cout << RED << "DirectX initialization failed!" << RESET << std::endl;
|
||||
}
|
||||
|
||||
//Best camera positions (Sorry for the magic numbers)
|
||||
m_SceneCameraPositions[SceneNames::Main] = {Vector3{0.f, 0.f, 0.f}, Vector3{0.f, 0.f, 0.f}};
|
||||
m_SceneCameraPositions[SceneNames::Diorama] = {Vector3{48.88f, 23.0f, -3.3f}, Vector3{-0.23f, 4.79f, 0}};
|
||||
m_SceneCameraPositions[SceneNames::Instanced] = {Vector3{11.8f, 12.4f, 12.9f}, Vector3{-0.30f, 0.76f, 0.f}};
|
||||
m_SceneCameraPositions[SceneNames::Planet] = {Vector3{-18.5f, 10.5f, -15.7f}, Vector3{-0.46f, 0.86f, 0}};
|
||||
|
||||
InitializeSDLRasterizer();
|
||||
|
||||
m_pScene = new MainScene();
|
||||
m_pScene->Initialize(m_DevicePtr);
|
||||
m_pScene->Initialize(m_DevicePtr, m_DeviceContextPtr);
|
||||
|
||||
m_pFireMesh = m_pScene->GetMeshes().back();
|
||||
if (!m_pScene->GetMeshes().empty()) {
|
||||
m_pFireMesh = m_pScene->GetMeshes().back();
|
||||
}
|
||||
|
||||
float aspectRatio = static_cast<float>(m_Width) / static_cast<float>(m_Height);
|
||||
m_Camera = Camera({.0f, .0f, .0f}, 45.f);
|
||||
@@ -80,7 +89,7 @@ namespace dae {
|
||||
|
||||
Matrix rotationMatrix = Matrix::CreateRotationY(rotationThisFrame);
|
||||
|
||||
for (auto mesh : m_pScene->GetMeshes()) {
|
||||
for (auto mesh: m_pScene->GetMeshes()) {
|
||||
Matrix originalWorldMatrix = mesh->GetWorldMatrix();
|
||||
Matrix world = rotationMatrix * originalWorldMatrix;
|
||||
|
||||
@@ -88,6 +97,7 @@ namespace dae {
|
||||
}
|
||||
}
|
||||
|
||||
m_pScene->Update();
|
||||
}
|
||||
|
||||
void Renderer::Render() {
|
||||
@@ -103,15 +113,16 @@ namespace dae {
|
||||
|
||||
void Renderer::RenderDirectX() const {
|
||||
//Clear back buffer
|
||||
ColorRGB ChosenClearColor = m_UseUniformClearColor ? m_UniformClearColor: DirectXClearColor;
|
||||
const float clearColor[] = {static_cast<float>(ChosenClearColor.r) / 255.f, static_cast<float>(ChosenClearColor.g) / 255.f, static_cast<float>(ChosenClearColor.b) / 255.f, 1.f};
|
||||
ColorRGB ChosenClearColor = m_UseUniformClearColor ? m_UniformClearColor : DirectXClearColor;
|
||||
const float clearColor[] = {static_cast<float>(ChosenClearColor.r) / 255.f, static_cast<float>(ChosenClearColor.g) / 255.f,
|
||||
static_cast<float>(ChosenClearColor.b) / 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_pScene->GetMeshes()) {
|
||||
if(mesh->GetShouldRender()){
|
||||
if (mesh->GetShouldRender()) {
|
||||
Matrix modelMatrix = mesh->GetWorldMatrix();
|
||||
Matrix worldViewProjMatrix = modelMatrix * viewProjMatrix;
|
||||
|
||||
@@ -119,6 +130,8 @@ namespace dae {
|
||||
}
|
||||
}
|
||||
|
||||
m_pScene->Render(m_DeviceContextPtr, m_RenderTargetViewPtr, m_DepthStencilViewPtr, m_Camera);
|
||||
|
||||
//Present
|
||||
m_SwapChainPtr->Present(0, 0);
|
||||
}
|
||||
@@ -136,13 +149,13 @@ namespace dae {
|
||||
m_VerticiesScreenSpace.clear();
|
||||
|
||||
|
||||
for (auto* currentMesh: m_pScene->GetMeshes()) {
|
||||
for (auto *currentMesh: m_pScene->GetMeshes()) {
|
||||
|
||||
if(!currentMesh->GetShouldRender()){
|
||||
if (!currentMesh->GetShouldRender()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const Matrix worldViewProjectionMatrix{ currentMesh->GetWorldMatrix() * m_Camera.GetViewProjectionMatrix() };
|
||||
const Matrix worldViewProjectionMatrix{currentMesh->GetWorldMatrix() * m_Camera.GetViewProjectionMatrix()};
|
||||
VertexTransformationFunction(worldViewProjectionMatrix, currentMesh, currentMesh->GetVertices(), m_VerticiesScreenSpace);
|
||||
|
||||
int numTriangles{};
|
||||
@@ -209,7 +222,7 @@ namespace dae {
|
||||
for (int px{startX}; px < endX; ++px) {
|
||||
for (int py{startY}; py < endY; ++py) {
|
||||
|
||||
if(m_isHitbox){
|
||||
if (m_isHitbox) {
|
||||
//Hitboxes
|
||||
m_pBackBufferPixels[px + (py * m_Width)] = SDL_MapRGB(m_pBackBuffer->format,
|
||||
static_cast<uint8_t>(255),
|
||||
@@ -226,15 +239,15 @@ namespace dae {
|
||||
|
||||
Vector3 P{static_cast<float>(px) + 0.5f, static_cast<float>(py) + 0.5f, 1.f};
|
||||
|
||||
auto sample{ TriangleHitTest(P, vertex0, vertex1, vertex2) };
|
||||
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 };
|
||||
const Vector3 fragPos{static_cast<float>(px) + 0.5f, static_cast<float>(py) + 0.5f, 1.f};
|
||||
|
||||
int depthBufferIndex{ px + (py * m_Width) };
|
||||
int depthBufferIndex{px + (py * m_Width)};
|
||||
|
||||
float min{.985f};
|
||||
float max{1.f};
|
||||
@@ -260,14 +273,13 @@ namespace dae {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockSurface(m_pBackBuffer);
|
||||
SDL_BlitSurface(m_pBackBuffer,nullptr, m_pFrontBuffer, nullptr);
|
||||
SDL_BlitSurface(m_pBackBuffer, nullptr, m_pFrontBuffer, nullptr);
|
||||
SDL_UpdateWindowSurface(m_pWindow);
|
||||
}
|
||||
|
||||
@@ -390,29 +402,27 @@ namespace dae {
|
||||
}
|
||||
|
||||
|
||||
void Renderer::VertexTransformationFunction(const Matrix &WorldViewProjectionMatrix, Mesh* mesh,
|
||||
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)
|
||||
{
|
||||
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) };
|
||||
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 };
|
||||
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)
|
||||
vertPos.z < 0.f || vertPos.z > 1.f)
|
||||
isValid = false;
|
||||
|
||||
vertPos.x = ((vertPos.x + 1.f) / 2.f) * static_cast<float>(m_Width);
|
||||
@@ -440,21 +450,22 @@ namespace dae {
|
||||
|
||||
ColorRGB Renderer::ShadePixel(const Sample &sample) {
|
||||
|
||||
Material* currentMaterial = sample.mesh->GetMaterial();
|
||||
Material *currentMaterial = sample.mesh->GetMaterial();
|
||||
|
||||
if(currentMaterial->normalTexturePtr == nullptr && currentMaterial->specularTexturePtr == nullptr && currentMaterial->glossTexturePtr == nullptr){
|
||||
if (currentMaterial->normalTexturePtr == nullptr && currentMaterial->specularTexturePtr == nullptr &&
|
||||
currentMaterial->glossTexturePtr == nullptr) {
|
||||
return currentMaterial->diffuseTexturePtr->Sample(sample.uv);
|
||||
}
|
||||
|
||||
Vector3 lightDirection = { .577f, -.577f, .577f};
|
||||
Vector3 lightDirection = {.577f, -.577f, .577f};
|
||||
Vector3 normal = sample.normal.Normalized();
|
||||
constexpr float lightIntensity{ 7.f };
|
||||
constexpr float lightIntensity{7.f};
|
||||
|
||||
ColorRGB color{ 1, 1, 1 };
|
||||
constexpr ColorRGB ambient{ .03f, .03f, .03f};
|
||||
ColorRGB color{1, 1, 1};
|
||||
constexpr ColorRGB ambient{.03f, .03f, .03f};
|
||||
|
||||
if(m_useNormals){
|
||||
const ColorRGB normalSample{ sample.mesh->GetMaterial()->normalTexturePtr->Sample(sample.uv) };
|
||||
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,
|
||||
@@ -462,26 +473,26 @@ namespace dae {
|
||||
0.f
|
||||
};
|
||||
|
||||
const Vector3 biNormal{ Vector3::Cross(normal, sample.tangent) };
|
||||
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 }
|
||||
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) };
|
||||
const ColorRGB diffuseSample{currentMaterial->diffuseTexturePtr->Sample(sample.uv)};
|
||||
double invPi = 1.0 / PI;
|
||||
const ColorRGB lambert{ diffuseSample * lightIntensity * invPi };
|
||||
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 };
|
||||
float specularReflectance{1.f};
|
||||
float shininess{25.f};
|
||||
|
||||
specularReflectance *= currentMaterial->glossTexturePtr->Sample(sample.uv).r;
|
||||
shininess *= currentMaterial->specularTexturePtr->Sample(sample.uv).r;
|
||||
@@ -494,7 +505,7 @@ namespace dae {
|
||||
return ambient;
|
||||
}
|
||||
|
||||
switch(m_ShadeMode){
|
||||
switch (m_ShadeMode) {
|
||||
case ShadeMode::ObservedArea:
|
||||
break;
|
||||
case ShadeMode::Diffuse:
|
||||
@@ -508,18 +519,18 @@ namespace dae {
|
||||
break;
|
||||
}
|
||||
|
||||
color *= ColorRGB{ cosAngle, cosAngle, cosAngle };
|
||||
color *= ColorRGB{cosAngle, cosAngle, cosAngle};
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void Renderer::CycleCullMode() {
|
||||
for(auto mesh: m_pScene->GetMeshes()){
|
||||
for (auto mesh: m_pScene->GetMeshes()) {
|
||||
mesh->CycleCullMode();
|
||||
}
|
||||
|
||||
std::string mode;
|
||||
switch(m_CullMode){
|
||||
switch (m_CullMode) {
|
||||
case CullMode::None:
|
||||
m_CullMode = CullMode::Front;
|
||||
mode = "Front";
|
||||
@@ -542,6 +553,11 @@ namespace dae {
|
||||
|
||||
std::string mode = m_isHitbox ? "ON" : "OFF";
|
||||
std::cout << MAGENTA << "[SOFTWARE]" << BLUE << " Hitbox " << mode << RESET << std::endl;
|
||||
|
||||
|
||||
std::cout << "Camera pos: " << m_Camera.GetPosition().x << " " << m_Camera.GetPosition().y << " " << m_Camera.GetPosition().z << std::endl;
|
||||
std::cout << "Camera rot: " << m_Camera.GetRotation().x << " " << m_Camera.GetRotation().y << " " << m_Camera.GetRotation().z << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void Renderer::CycleRenderingMode() {
|
||||
@@ -582,12 +598,12 @@ namespace dae {
|
||||
}
|
||||
|
||||
void Renderer::NextSamplingState() {
|
||||
for(auto mesh: m_pScene->GetMeshes()){
|
||||
for (auto mesh: m_pScene->GetMeshes()) {
|
||||
mesh->NextSamplingState();
|
||||
}
|
||||
|
||||
std::string mode;
|
||||
switch(m_TechniqueType){
|
||||
switch (m_TechniqueType) {
|
||||
case TechniqueType::Point:
|
||||
m_TechniqueType = TechniqueType::Linear;
|
||||
mode = "Linear";
|
||||
@@ -607,7 +623,7 @@ namespace dae {
|
||||
|
||||
void Renderer::ToggleNormals() {
|
||||
m_useNormals = !m_useNormals;
|
||||
for(auto mesh: m_pScene->GetMeshes()){
|
||||
for (auto mesh: m_pScene->GetMeshes()) {
|
||||
mesh->ToggleNormals();
|
||||
}
|
||||
std::string mode = m_useNormals ? "ON" : "OFF";
|
||||
@@ -627,7 +643,7 @@ namespace dae {
|
||||
}
|
||||
|
||||
void Renderer::ToggleFireFX() {
|
||||
if(m_pFireMesh != nullptr){
|
||||
if (m_pFireMesh != nullptr) {
|
||||
m_pFireMesh->SetShouldRender(!m_pFireMesh->GetShouldRender());
|
||||
std::string mode = m_pFireMesh->GetShouldRender() ? "ON" : "OFF";
|
||||
std::cout << MAGENTA << "[HARDWARE]" << BLUE << " FireFX " << mode << RESET << std::endl;
|
||||
@@ -637,25 +653,51 @@ namespace dae {
|
||||
void Renderer::NextScene() {
|
||||
m_pScene->Cleanup();
|
||||
delete m_pScene;
|
||||
if(m_CurrentScene == SceneNames::Main){
|
||||
m_pScene = new DioramaScene();
|
||||
m_pFireMesh = nullptr;
|
||||
m_CurrentScene = SceneNames::Diorama;
|
||||
|
||||
std::cout << MAGENTA << "[SHARED]" << BLUE << " Scene = Diorama" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
//Calculate the next scene
|
||||
int index = static_cast<int>(m_CurrentScene);
|
||||
index = (index + 1) % static_cast<int>(SceneNames::Count);
|
||||
m_CurrentScene = static_cast<SceneNames>(index);
|
||||
|
||||
} else {
|
||||
m_pScene = new MainScene();
|
||||
m_CurrentScene = SceneNames::Main;
|
||||
switch (m_CurrentScene) {
|
||||
case SceneNames::Main:
|
||||
m_pScene = new MainScene();
|
||||
m_pFireMesh = nullptr;
|
||||
|
||||
std::cout << MAGENTA << "[SHARED]" << BLUE << " Scene = Main" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "[SHARED]" << BLUE << " Scene = Main" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
break;
|
||||
case SceneNames::Diorama:
|
||||
m_pScene = new DioramaScene();
|
||||
|
||||
std::cout << MAGENTA << "[SHARED]" << BLUE << " Scene = Diorama" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
break;
|
||||
case SceneNames::Instanced:
|
||||
m_pScene = new InstancedScene();
|
||||
|
||||
std::cout << MAGENTA << "[SHARED]" << BLUE << " Scene = Instanced" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
break;
|
||||
|
||||
case SceneNames::Planet:
|
||||
m_pScene = new PlanetScene();
|
||||
|
||||
std::cout << MAGENTA << "[SHARED]" << BLUE << " Scene = Planet" << RESET << std::endl;
|
||||
std::cout << MAGENTA << "This could take a second" << RESET << std::endl;
|
||||
break;
|
||||
|
||||
case SceneNames::Count:
|
||||
break;
|
||||
}
|
||||
m_pScene->Initialize(m_DevicePtr);
|
||||
|
||||
m_Camera.SetPosition(m_SceneCameraPositions[m_CurrentScene].first);
|
||||
m_Camera.SetRotation(m_SceneCameraPositions[m_CurrentScene].second);
|
||||
|
||||
m_pScene->Initialize(m_DevicePtr, m_DeviceContextPtr);
|
||||
|
||||
|
||||
if(m_CurrentScene == SceneNames::Main) {
|
||||
if (m_CurrentScene == SceneNames::Main) {
|
||||
//Kind of sloppy fix but hey :p
|
||||
m_pFireMesh = m_pScene->GetMeshes().back();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "Scenes/BaseScene.h"
|
||||
#include "Effects/Effect.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
struct SDL_Window;
|
||||
struct SDL_Surface;
|
||||
|
||||
@@ -23,7 +25,11 @@ enum class ShadeMode{
|
||||
|
||||
enum class SceneNames{
|
||||
Main,
|
||||
Diorama
|
||||
Diorama,
|
||||
Instanced,
|
||||
Planet,
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
namespace dae
|
||||
@@ -75,6 +81,8 @@ namespace dae
|
||||
|
||||
BaseScene* m_pScene{};
|
||||
SceneNames m_CurrentScene{ SceneNames::Main };
|
||||
//Pos rot
|
||||
std::unordered_map<SceneNames, std::pair<Vector3, Vector3>> m_SceneCameraPositions{};
|
||||
|
||||
Camera m_Camera{};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "../Mesh.h"
|
||||
#include "../Material.h"
|
||||
#include "../Camera.h"
|
||||
|
||||
|
||||
class BaseScene {
|
||||
@@ -16,11 +17,11 @@ public:
|
||||
|
||||
virtual ~BaseScene() = default;
|
||||
|
||||
virtual void Initialize(ID3D11Device *DevicePtr) = 0;
|
||||
virtual void Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) = 0;
|
||||
|
||||
// virtual void Update() = 0;
|
||||
virtual void Update() = 0;
|
||||
|
||||
// virtual void Render() = 0;
|
||||
virtual void Render(ID3D11DeviceContext* devicePtr, ID3D11RenderTargetView *renderTargetViewPtr, ID3D11DepthStencilView *depthStencilViewPtr, const Camera& camera) = 0;
|
||||
|
||||
virtual void Cleanup() = 0;
|
||||
|
||||
|
||||
@@ -10,48 +10,45 @@
|
||||
#include <iostream>
|
||||
|
||||
|
||||
void DioramaScene::Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) {
|
||||
|
||||
void DioramaScene::Initialize(ID3D11Device *DevicePtr) {
|
||||
std::vector<std::unique_ptr<Utils::MaterialMesh>> materialMeshes;
|
||||
Utils::LoadObjWithMaterials("resources/scene.obj", materialMeshes, true, DevicePtr);
|
||||
for (const auto &mesh: materialMeshes) {
|
||||
if (mesh->vertices.size() > 0) {
|
||||
std::shared_ptr<Material> material = std::make_shared<Material>();
|
||||
BaseEffect *effect{nullptr};
|
||||
|
||||
std::vector<std::unique_ptr<Utils::MaterialMesh>> materialMeshes;
|
||||
Utils::LoadObjWithMaterials("resources/scene.obj", materialMeshes, true, DevicePtr);
|
||||
for (const auto &mesh: materialMeshes) {
|
||||
if(mesh->vertices.size() > 0) {
|
||||
std::shared_ptr<Material> material = std::make_shared<Material>();
|
||||
BaseEffect *effect{ nullptr };
|
||||
|
||||
if(mesh->opacity_map != ""){
|
||||
// std::cout << "Opacity map found" << mesh->opacity_map << std::endl;
|
||||
effect = new FireEffect(DevicePtr, L"resources/Fire.fx");
|
||||
material->diffuseTexturePtr = Texture::LoadFromFile("./resources/diorama/" + mesh->diffuse_texture, DevicePtr);
|
||||
// material-> = Texture::LoadFromFile("./resources/" + mesh->opacity_map, DevicePtr);
|
||||
} else {
|
||||
material->diffuseTexturePtr = Texture::LoadFromFile("./resources/diorama/" + mesh->diffuse_texture, DevicePtr);
|
||||
effect = new Effect(DevicePtr, L"resources/SimpleDiffuse.fx");
|
||||
}
|
||||
|
||||
|
||||
m_meshes.push_back(new Mesh(DevicePtr, mesh->vertices, mesh->indices, material, effect));
|
||||
|
||||
Matrix worldMatrix = m_meshes.back()->GetWorldMatrix();
|
||||
worldMatrix *= Matrix::CreateScale(2.f, 2.f, 2.f);
|
||||
worldMatrix *= Matrix::CreateScale(-1.f, 1.f, 1.f);
|
||||
m_meshes.back()->SetWorldMatrix(worldMatrix);
|
||||
if (mesh->opacity_map != "") {
|
||||
effect = new FireEffect(DevicePtr, L"resources/Fire.fx");
|
||||
material->diffuseTexturePtr = Texture::LoadFromFile("./resources/diorama/" + mesh->diffuse_texture, DevicePtr);
|
||||
} else {
|
||||
material->diffuseTexturePtr = Texture::LoadFromFile("./resources/diorama/" + mesh->diffuse_texture, DevicePtr);
|
||||
effect = new Effect(DevicePtr, L"resources/SimpleDiffuse.fx");
|
||||
}
|
||||
}
|
||||
|
||||
m_meshes.push_back(new Mesh(DevicePtr, mesh->vertices, mesh->indices, material, effect));
|
||||
|
||||
Matrix worldMatrix = m_meshes.back()->GetWorldMatrix();
|
||||
worldMatrix *= Matrix::CreateScale(2.f, 2.f, 2.f);
|
||||
worldMatrix *= Matrix::CreateScale(-1.f, 1.f, 1.f); // Mirror the model (Possible loading fault)
|
||||
m_meshes.back()->SetWorldMatrix(worldMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
//Load brok
|
||||
materialMeshes.clear();
|
||||
Utils::LoadObjWithMaterials("resources/brok/brok.obj", materialMeshes, true, DevicePtr);
|
||||
for (const auto &mesh: materialMeshes) {
|
||||
if(mesh->vertices.size() > 0) {
|
||||
if (!mesh->vertices.empty()) {
|
||||
std::shared_ptr<Material> material = std::make_shared<Material>();
|
||||
BaseEffect *effect{ nullptr };
|
||||
BaseEffect *effect{nullptr};
|
||||
|
||||
effect = new Effect(DevicePtr, L"resources/SimpleDiffuse.fx");
|
||||
material->diffuseTexturePtr = Texture::LoadFromFile("./resources/brok/" + mesh->diffuse_texture, DevicePtr);
|
||||
|
||||
|
||||
m_meshes.push_back(new Mesh(DevicePtr, mesh->vertices, mesh->indices, material, effect));
|
||||
m_brokMeshses.push_back(m_meshes.back());
|
||||
|
||||
Matrix worldMatrix = m_meshes.back()->GetWorldMatrix();
|
||||
worldMatrix *= Matrix::CreateRotationY(3.14f / 2.f);
|
||||
@@ -63,6 +60,27 @@ void DioramaScene::Initialize(ID3D11Device *DevicePtr) {
|
||||
}
|
||||
}
|
||||
|
||||
void DioramaScene::Update() {
|
||||
m_brokTimer += 0.01f;
|
||||
for(auto* mesh : m_brokMeshses){
|
||||
if(mesh == nullptr)
|
||||
continue;
|
||||
Matrix worldMatrix = mesh->GetWorldMatrix();
|
||||
|
||||
float YOffset = sin(m_brokTimer) / 2000.f;
|
||||
|
||||
worldMatrix *= Matrix::CreateTranslation(0.f, YOffset, 0.f);
|
||||
|
||||
mesh->SetWorldMatrix(worldMatrix);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DioramaScene::Render(ID3D11DeviceContext *devicePtr, ID3D11RenderTargetView *renderTargetViewPtr,
|
||||
ID3D11DepthStencilView *depthStencilViewPtr, const Camera &camera) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<Mesh *> &DioramaScene::GetMeshes() {
|
||||
return m_meshes;
|
||||
}
|
||||
@@ -72,7 +90,7 @@ std::vector<std::shared_ptr<Material>> &DioramaScene::GetMaterials() {
|
||||
}
|
||||
|
||||
void DioramaScene::Cleanup() {
|
||||
for (Mesh *mesh : m_meshes) {
|
||||
for (Mesh *mesh: m_meshes) {
|
||||
delete mesh;
|
||||
}
|
||||
m_meshes.clear();
|
||||
|
||||
@@ -7,15 +7,23 @@ class DioramaScene : public BaseScene {
|
||||
public:
|
||||
void Cleanup() override;
|
||||
|
||||
void Initialize(ID3D11Device *DevicePtr) override;
|
||||
void Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) override;
|
||||
|
||||
std::vector<Mesh *> &GetMeshes() override;
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &GetMaterials() override;
|
||||
|
||||
void Update() override;
|
||||
|
||||
void Render(ID3D11DeviceContext* devicePtr, ID3D11RenderTargetView *renderTargetViewPtr, ID3D11DepthStencilView *depthStencilViewPtr, const Camera& camera) override;
|
||||
|
||||
private:
|
||||
std::vector<Mesh *> m_meshes{};
|
||||
std::vector<std::shared_ptr<Material>> m_materials{};
|
||||
|
||||
std::vector<Mesh*> m_brokMeshses{ nullptr };
|
||||
|
||||
float m_brokTimer{ 0.f };
|
||||
};
|
||||
|
||||
#endif //GP1_DIRECTX_DIORAMASCENE_H
|
||||
|
||||
95
project/src/Scenes/InstancedScene.cpp
Normal file
95
project/src/Scenes/InstancedScene.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// Created by Bram on 28/12/2024.
|
||||
//
|
||||
|
||||
#include "InstancedScene.h"
|
||||
#include "../Utils.h"
|
||||
#include "../Effects/Effect.h"
|
||||
|
||||
void InstancedScene::Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) {
|
||||
m_DeviceContextPtr = DeviceContextPtr;
|
||||
|
||||
std::vector<VertexIn> vertices{};
|
||||
std::vector<uint32_t> indices{};
|
||||
|
||||
if (!Utils::ParseOBJNew("resources/cube.obj", vertices, indices, false)) {
|
||||
std::cout << "Model failed to load" << std::endl;
|
||||
assert(true && "Model failed to load");
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> cubeMaterial = std::make_shared<Material>();
|
||||
cubeMaterial->diffuseTexturePtr = Texture::LoadFromFile("resources/grass_block.png", DevicePtr);
|
||||
|
||||
std::vector<InstancedData> instanceData;
|
||||
for (int x = 0; x < 100; ++x) {
|
||||
for (int y = 0; y < 100; ++y) {
|
||||
InstancedData data;
|
||||
float scale = 2;
|
||||
//Generate sine wave based on x and y
|
||||
float YOffset = sin(x * 0.5f + SDL_GetTicks() * 0.001f) + cos(y * 0.5f + SDL_GetTicks() * 0.001f);
|
||||
//Add random but predictable randomness
|
||||
YOffset += (x * 0.1f + y * 0.1f) * 0.1f;
|
||||
data.worldMatrix = Matrix::CreateTranslation(x * scale, YOffset, y * scale);
|
||||
data.worldMatrix *= Matrix::CreateScale(0.5f, 0.5f, 0.5f);
|
||||
data.color = Vector4(float(x) / 255.f, float(y) / 255.f, 1.f, 1.0f);
|
||||
instanceData.push_back(data);
|
||||
}
|
||||
}
|
||||
|
||||
auto *effect = new Effect(DevicePtr, L"resources/InstancedSimpleDiffuse.fx");
|
||||
effect->NextSamplingState();
|
||||
effect->NextSamplingState(); //Dirty hack
|
||||
m_instancedMeshes.push_back(new InstancedMesh(DevicePtr, vertices, indices, cubeMaterial, effect, instanceData));
|
||||
}
|
||||
|
||||
void InstancedScene::Cleanup() {
|
||||
for (auto mesh: m_instancedMeshes) {
|
||||
delete mesh;
|
||||
}
|
||||
m_instancedMeshes.clear();
|
||||
|
||||
for (auto mesh: m_meshes) {
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
m_meshes.clear();
|
||||
}
|
||||
|
||||
std::vector<Mesh *> &InstancedScene::GetMeshes() {
|
||||
return m_meshes;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &InstancedScene::GetMaterials() {
|
||||
return m_materials;
|
||||
}
|
||||
|
||||
void InstancedScene::Render(ID3D11DeviceContext *devicePtr, ID3D11RenderTargetView *renderTargetViewPtr,
|
||||
ID3D11DepthStencilView *depthStencilViewPtr, const Camera &camera) {
|
||||
Matrix viewProjMatrix = camera.GetViewProjectionMatrix();
|
||||
for (auto mesh: m_instancedMeshes) {
|
||||
Matrix modelMatrix = mesh->GetWorldMatrix();
|
||||
Matrix worldViewProjMatrix = modelMatrix * viewProjMatrix;
|
||||
mesh->Render(devicePtr, worldViewProjMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
void InstancedScene::Update() {
|
||||
if (SDL_GetTicks() % 3 == 0) {
|
||||
std::vector<InstancedData> instanceData;
|
||||
for (int x = 0; x < 100; ++x) {
|
||||
for (int y = 0; y < 100; ++y) {
|
||||
InstancedData data;
|
||||
float scale = 2;
|
||||
//Generate sine wave based on x and y and the SDL_GetTicks
|
||||
float YOffset = sin(x * 0.5f + SDL_GetTicks() * 0.001f) + cos(y * 0.5f + SDL_GetTicks() * 0.001f);
|
||||
YOffset += (x * 0.1f + y * 0.1f) * 0.1f;
|
||||
|
||||
data.worldMatrix = Matrix::CreateTranslation(x * scale, YOffset, y * scale);
|
||||
data.worldMatrix *= Matrix::CreateScale(0.5f, 0.5f, 0.5f);
|
||||
data.color = Vector4(float(x) / 255.f, float(y) / 255.f, 1.f, 1.0f);
|
||||
instanceData.push_back(data);
|
||||
}
|
||||
}
|
||||
m_instancedMeshes[0]->UpdateInstanceData(m_DeviceContextPtr, instanceData);
|
||||
}
|
||||
}
|
||||
32
project/src/Scenes/InstancedScene.h
Normal file
32
project/src/Scenes/InstancedScene.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef GP1_DIRECTX_INSTANCEDSCENE_H
|
||||
#define GP1_DIRECTX_INSTANCEDSCENE_H
|
||||
|
||||
#include "BaseScene.h"
|
||||
#include "../Camera.h"
|
||||
#include "../InstancedMesh.h"
|
||||
|
||||
class InstancedScene : public BaseScene {
|
||||
public:
|
||||
void Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) override;
|
||||
|
||||
void Render(ID3D11DeviceContext* devicePtr, ID3D11RenderTargetView *renderTargetViewPtr, ID3D11DepthStencilView *depthStencilViewPtr, const Camera& camera) override;
|
||||
|
||||
void Update() override;
|
||||
|
||||
void Cleanup() override;
|
||||
|
||||
std::vector<Mesh *> &GetMeshes() override;
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &GetMaterials() override;
|
||||
|
||||
private:
|
||||
|
||||
ID3D11DeviceContext* m_DeviceContextPtr{};
|
||||
|
||||
std::vector<Mesh*> m_meshes;
|
||||
//Kind of hack since InstancedMesh doesnt extend mesh
|
||||
std::vector<InstancedMesh*> m_instancedMeshes;
|
||||
std::vector<std::shared_ptr<Material>> m_materials;
|
||||
};
|
||||
|
||||
#endif //GP1_DIRECTX_INSTANCEDSCENE_H
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <cassert>
|
||||
|
||||
|
||||
void MainScene::Initialize(ID3D11Device *DevicePtr) {
|
||||
void MainScene::Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) {
|
||||
|
||||
std::vector<VertexIn> vertices{};
|
||||
std::vector<uint32_t> indices{};
|
||||
@@ -69,3 +69,11 @@ std::vector<std::shared_ptr<Material>> &MainScene::GetMaterials() {
|
||||
return m_materials;
|
||||
}
|
||||
|
||||
void MainScene::Update() {
|
||||
|
||||
}
|
||||
|
||||
void MainScene::Render(ID3D11DeviceContext* devicePtr, ID3D11RenderTargetView *renderTargetViewPtr, ID3D11DepthStencilView *depthStencilViewPtr, const Camera& camera) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
class MainScene : public BaseScene {
|
||||
public:
|
||||
void Initialize(ID3D11Device* DevicePtr) override;
|
||||
void Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) override;
|
||||
|
||||
void Cleanup() override;
|
||||
|
||||
@@ -20,6 +20,10 @@ public:
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &GetMaterials() override;
|
||||
|
||||
void Update() override;
|
||||
|
||||
void Render(ID3D11DeviceContext* devicePtr, ID3D11RenderTargetView *renderTargetViewPtr, ID3D11DepthStencilView *depthStencilViewPtr, const Camera& camera) override;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
136
project/src/Scenes/PlanetScene.cpp
Normal file
136
project/src/Scenes/PlanetScene.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
#include "PlanetScene.h"
|
||||
|
||||
#include "../Utils.h"
|
||||
#include "../Effects/Effect.h"
|
||||
|
||||
void PlanetScene::Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) {
|
||||
m_DeviceContextPtr = DeviceContextPtr;
|
||||
|
||||
std::vector<VertexIn> vertices{};
|
||||
std::vector<uint32_t> indices{};
|
||||
|
||||
if (!Utils::ParseOBJNew("resources/planet/rock/rock.obj", vertices, indices, false)) {
|
||||
std::cout << "Model failed to load" << std::endl;
|
||||
assert(true && "Model failed to load");
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> rockMaterial = std::make_shared<Material>();
|
||||
rockMaterial->diffuseTexturePtr = Texture::LoadFromFile("resources/planet/rock/rock.png", DevicePtr);
|
||||
|
||||
|
||||
unsigned int amount = 1000; // Adjusted for a different number of instances
|
||||
float radius = 50.0f;
|
||||
float offset = 2.5f;
|
||||
float scale = 0.25f; // Random scale factor
|
||||
|
||||
for (unsigned int i = 0; i < amount; ++i) {
|
||||
InstancedData data;
|
||||
|
||||
// Generate translation: displace along circle with 'radius' and apply random offset
|
||||
float angle = static_cast<float>(i) / static_cast<float>(amount) * 360.0f;
|
||||
float displacement = static_cast<float>(rand() % static_cast<int>(2 * offset * 100)) / 100.0f - offset;
|
||||
float x = sin(angle) * radius + displacement;
|
||||
displacement = static_cast<float>(rand() % static_cast<int>(2 * offset * 100)) / 100.0f - offset;
|
||||
float y = displacement * 0.4f; // Keep height smaller compared to width of x and z
|
||||
displacement = static_cast<float>(rand() % static_cast<int>(2 * offset * 100)) / 100.0f - offset;
|
||||
float z = cos(angle) * radius + displacement;
|
||||
|
||||
data.worldMatrix = Matrix();
|
||||
|
||||
//Rotate the model randomly
|
||||
data.worldMatrix *= Matrix::CreateRotationY(static_cast<float>(rand() % 360));
|
||||
data.worldMatrix *= Matrix::CreateRotationX(static_cast<float>(rand() % 360));
|
||||
data.worldMatrix *= Matrix::CreateRotationZ(static_cast<float>(rand() % 360));
|
||||
|
||||
// Create translation matrix
|
||||
data.worldMatrix *= Matrix::CreateTranslation(x, y, z);
|
||||
|
||||
|
||||
// Apply scaling (randomized)
|
||||
float randScale = (rand() % 20) / 100.0f + 0.05f; // Random scale between 0.05 and 0.25
|
||||
data.worldMatrix *= Matrix::CreateScale(randScale, randScale, randScale);
|
||||
|
||||
// Apply random rotation
|
||||
// float rotAngle = static_cast<float>(rand() % 360); // Random rotation angle
|
||||
// data.worldMatrix *= Matrix::CreateRotation(0.4f, 0.6f, 0.8f); // Apply rotation around random axis
|
||||
|
||||
// Set color (randomized based on position)
|
||||
data.color = Vector4(remap(rand(), 0, RAND_MAX, 0, 1.f),remap(rand(), 0, RAND_MAX, 0, 1.f), remap(rand(), 0, RAND_MAX, 0, 1.f), 1.0f);
|
||||
|
||||
m_InstancedData.push_back(data);
|
||||
}
|
||||
|
||||
auto *rockEffect = new Effect(DevicePtr, L"resources/InstancedSimpleDiffuse.fx");
|
||||
m_instancedMeshes.push_back(new InstancedMesh(DevicePtr, vertices, indices, rockMaterial, rockEffect, m_InstancedData));
|
||||
|
||||
indices.clear();
|
||||
vertices.clear();
|
||||
|
||||
if (!Utils::ParseOBJNew("resources/planet/planet.obj", vertices, indices, false)) {
|
||||
std::cout << "Model failed to load" << std::endl;
|
||||
assert(true && "Model failed to load");
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> planetMaterial = std::make_shared<Material>();
|
||||
planetMaterial->diffuseTexturePtr = Texture::LoadFromFile("resources/planet/mars.png", DevicePtr);
|
||||
|
||||
auto* planetEffect = new Effect(DevicePtr, L"resources/SimpleDiffuse.fx");
|
||||
m_meshes.push_back(new Mesh(DevicePtr, vertices, indices, planetMaterial, planetEffect));
|
||||
|
||||
indices.clear();
|
||||
vertices.clear();
|
||||
|
||||
if (!Utils::ParseOBJNew("resources/planet/skybox/skybox.obj", vertices, indices, false)) {
|
||||
std::cout << "Model failed to load" << std::endl;
|
||||
assert(true && "Model failed to load");
|
||||
}
|
||||
|
||||
std::shared_ptr<Material> skyboxMaterial = std::make_shared<Material>();
|
||||
skyboxMaterial->diffuseTexturePtr = Texture::LoadFromFile("resources/planet/skybox/space_nebula_6k.png", DevicePtr);
|
||||
|
||||
auto* skyboxEffect = new Effect(DevicePtr, L"resources/SimpleDiffuse.fx");
|
||||
m_meshes.push_back(new Mesh(DevicePtr, vertices, indices, skyboxMaterial, skyboxEffect));
|
||||
|
||||
Matrix worldMatrix = m_meshes.back()->GetWorldMatrix();
|
||||
worldMatrix *= Matrix::CreateScale(0.1f, 0.1f, 0.1f);
|
||||
m_meshes.back()->SetWorldMatrix(worldMatrix);
|
||||
}
|
||||
|
||||
void PlanetScene::Cleanup() {
|
||||
for (auto mesh: m_instancedMeshes) {
|
||||
delete mesh;
|
||||
}
|
||||
m_instancedMeshes.clear();
|
||||
|
||||
for (auto mesh: m_meshes) {
|
||||
delete mesh;
|
||||
}
|
||||
|
||||
m_meshes.clear();
|
||||
}
|
||||
|
||||
std::vector<Mesh *> &PlanetScene::GetMeshes() {
|
||||
return m_meshes;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &PlanetScene::GetMaterials() {
|
||||
return m_materials;
|
||||
}
|
||||
|
||||
void PlanetScene::Render(ID3D11DeviceContext *devicePtr, ID3D11RenderTargetView *renderTargetViewPtr,
|
||||
ID3D11DepthStencilView *depthStencilViewPtr, const Camera &camera) {
|
||||
Matrix viewProjMatrix = camera.GetViewProjectionMatrix();
|
||||
for (auto mesh: m_instancedMeshes) {
|
||||
Matrix modelMatrix = mesh->GetWorldMatrix();
|
||||
Matrix worldViewProjMatrix = modelMatrix * viewProjMatrix;
|
||||
mesh->Render(devicePtr, worldViewProjMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
void PlanetScene::Update() {
|
||||
for (auto& data : m_InstancedData) {
|
||||
data.worldMatrix *= Matrix::CreateRotationY(remap(rand(), 0, RAND_MAX, 0.00001f, 0.0002f));
|
||||
}
|
||||
|
||||
m_instancedMeshes[0]->UpdateInstanceData(m_DeviceContextPtr, m_InstancedData);
|
||||
}
|
||||
35
project/src/Scenes/PlanetScene.h
Normal file
35
project/src/Scenes/PlanetScene.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef GP1_DIRECTX_PLANETSCENE_H
|
||||
#define GP1_DIRECTX_PLANETSCENE_H
|
||||
|
||||
//https://learnopengl.com/Advanced-OpenGL/Instancing
|
||||
|
||||
#include "BaseScene.h"
|
||||
#include "../InstancedMesh.h"
|
||||
|
||||
class PlanetScene : public BaseScene {
|
||||
public:
|
||||
void Initialize(ID3D11Device *DevicePtr, ID3D11DeviceContext *DeviceContextPtr) override;
|
||||
|
||||
void Render(ID3D11DeviceContext* devicePtr, ID3D11RenderTargetView *renderTargetViewPtr, ID3D11DepthStencilView *depthStencilViewPtr, const Camera& camera) override;
|
||||
|
||||
void Update() override;
|
||||
|
||||
void Cleanup() override;
|
||||
|
||||
std::vector<Mesh *> &GetMeshes() override;
|
||||
|
||||
std::vector<std::shared_ptr<Material>> &GetMaterials() override;
|
||||
|
||||
private:
|
||||
|
||||
ID3D11DeviceContext* m_DeviceContextPtr{};
|
||||
|
||||
std::vector<Mesh*> m_meshes;
|
||||
//Kind of hack since InstancedMesh doesnt extend mesh
|
||||
std::vector<InstancedMesh*> m_instancedMeshes;
|
||||
std::vector<InstancedData> m_InstancedData;
|
||||
std::vector<std::shared_ptr<Material>> m_materials;
|
||||
};
|
||||
|
||||
|
||||
#endif //GP1_DIRECTX_PLANETSCENE_H
|
||||
@@ -124,6 +124,8 @@ int main(int argc, char *args[]) {
|
||||
(void) argc;
|
||||
(void) args;
|
||||
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
|
||||
//Create window + surfaces
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user