Add Instanced Rendering / 2 more scenes

This commit is contained in:
2024-12-28 17:24:11 +01:00
parent 033909656a
commit 5e28e5fff4
30 changed files with 13730 additions and 100 deletions

View File

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

View File

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

View 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);
}

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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);
}
}

View 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

View File

@@ -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) {
}

View File

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

View 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);
}

View 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

View File

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