210 lines
6.7 KiB
C++
210 lines
6.7 KiB
C++
#include "MetaCoreRender/MetaCoreSceneRenderer.h"
|
|
|
|
#include "MetaCoreRender/MetaCoreDebugGeometry.h"
|
|
#include "MetaCoreRender/MetaCoreShaderProgram.h"
|
|
#include "MetaCoreScene/MetaCoreScene.h"
|
|
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
namespace MetaCore {
|
|
|
|
class MetaCoreSceneRenderer::MetaCoreSceneRendererImpl {
|
|
public:
|
|
MetaCoreDebugGeometry DebugGeometry{};
|
|
MetaCoreShaderProgram LineShader{};
|
|
MetaCoreShaderProgram LitShader{};
|
|
};
|
|
|
|
namespace {
|
|
|
|
glm::mat4 MetaCoreBuildTransformMatrix(const MetaCoreTransformComponent& transform) {
|
|
glm::mat4 model(1.0F);
|
|
model = glm::translate(model, transform.Position);
|
|
model = glm::rotate(model, glm::radians(transform.RotationEulerDegrees.x), glm::vec3(1.0F, 0.0F, 0.0F));
|
|
model = glm::rotate(model, glm::radians(transform.RotationEulerDegrees.y), glm::vec3(0.0F, 1.0F, 0.0F));
|
|
model = glm::rotate(model, glm::radians(transform.RotationEulerDegrees.z), glm::vec3(0.0F, 0.0F, 1.0F));
|
|
model = glm::scale(model, transform.Scale);
|
|
return model;
|
|
}
|
|
|
|
glm::vec3 MetaCoreResolveLightDirection(const MetaCoreScene& scene) {
|
|
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
if (object.Light.has_value()) {
|
|
glm::mat4 rotation(1.0F);
|
|
rotation = glm::rotate(rotation, glm::radians(object.Transform.RotationEulerDegrees.x), glm::vec3(1.0F, 0.0F, 0.0F));
|
|
rotation = glm::rotate(rotation, glm::radians(object.Transform.RotationEulerDegrees.y), glm::vec3(0.0F, 1.0F, 0.0F));
|
|
rotation = glm::rotate(rotation, glm::radians(object.Transform.RotationEulerDegrees.z), glm::vec3(0.0F, 0.0F, 1.0F));
|
|
return glm::normalize(glm::vec3(rotation * glm::vec4(0.15F, -1.0F, -0.35F, 0.0F)));
|
|
}
|
|
}
|
|
return glm::normalize(glm::vec3(0.15F, -1.0F, -0.35F));
|
|
}
|
|
|
|
float MetaCoreResolveLightIntensity(const MetaCoreScene& scene) {
|
|
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
if (object.Light.has_value()) {
|
|
return object.Light->Intensity;
|
|
}
|
|
}
|
|
return 1.5F;
|
|
}
|
|
|
|
glm::vec3 MetaCoreResolveLightColor(const MetaCoreScene& scene) {
|
|
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
if (object.Light.has_value()) {
|
|
return object.Light->Color;
|
|
}
|
|
}
|
|
return glm::vec3(1.0F, 1.0F, 1.0F);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool MetaCoreSceneRenderer::Initialize() {
|
|
Shutdown();
|
|
|
|
Impl_ = new MetaCoreSceneRendererImpl();
|
|
if (!Impl_->DebugGeometry.Initialize()) {
|
|
Shutdown();
|
|
return false;
|
|
}
|
|
|
|
std::string errorMessage;
|
|
|
|
const std::string lineVertexShader = R"(
|
|
#version 330 core
|
|
layout (location = 0) in vec3 aPosition;
|
|
layout (location = 2) in vec4 aColor;
|
|
|
|
uniform mat4 uView;
|
|
uniform mat4 uProjection;
|
|
uniform mat4 uModel;
|
|
|
|
out vec4 vColor;
|
|
|
|
void main() {
|
|
vColor = aColor;
|
|
gl_Position = uProjection * uView * uModel * vec4(aPosition, 1.0);
|
|
}
|
|
)";
|
|
|
|
const std::string lineFragmentShader = R"(
|
|
#version 330 core
|
|
in vec4 vColor;
|
|
out vec4 FragColor;
|
|
|
|
void main() {
|
|
FragColor = vColor;
|
|
}
|
|
)";
|
|
|
|
const std::string litVertexShader = R"(
|
|
#version 330 core
|
|
layout (location = 0) in vec3 aPosition;
|
|
layout (location = 1) in vec3 aNormal;
|
|
|
|
uniform mat4 uView;
|
|
uniform mat4 uProjection;
|
|
uniform mat4 uModel;
|
|
|
|
out vec3 vWorldPosition;
|
|
out vec3 vWorldNormal;
|
|
|
|
void main() {
|
|
vec4 worldPosition = uModel * vec4(aPosition, 1.0);
|
|
vWorldPosition = worldPosition.xyz;
|
|
vWorldNormal = normalize(mat3(transpose(inverse(uModel))) * aNormal);
|
|
gl_Position = uProjection * uView * worldPosition;
|
|
}
|
|
)";
|
|
|
|
const std::string litFragmentShader = R"(
|
|
#version 330 core
|
|
in vec3 vWorldPosition;
|
|
in vec3 vWorldNormal;
|
|
|
|
uniform vec3 uBaseColor;
|
|
uniform vec3 uLightDirection;
|
|
uniform vec3 uLightColor;
|
|
uniform float uLightIntensity;
|
|
|
|
out vec4 FragColor;
|
|
|
|
void main() {
|
|
vec3 normal = normalize(vWorldNormal);
|
|
vec3 lightDirection = normalize(-uLightDirection);
|
|
float diffuse = max(dot(normal, lightDirection), 0.0);
|
|
vec3 ambient = uBaseColor * 0.28;
|
|
vec3 lighting = ambient + (uBaseColor * uLightColor * diffuse * uLightIntensity);
|
|
FragColor = vec4(lighting, 1.0);
|
|
}
|
|
)";
|
|
|
|
if (!Impl_->LineShader.BuildFromSource(lineVertexShader, lineFragmentShader, errorMessage)) {
|
|
Shutdown();
|
|
return false;
|
|
}
|
|
|
|
if (!Impl_->LitShader.BuildFromSource(litVertexShader, litFragmentShader, errorMessage)) {
|
|
Shutdown();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void MetaCoreSceneRenderer::Shutdown() {
|
|
if (Impl_ != nullptr) {
|
|
Impl_->DebugGeometry.Shutdown();
|
|
Impl_->LineShader.Shutdown();
|
|
Impl_->LitShader.Shutdown();
|
|
delete Impl_;
|
|
Impl_ = nullptr;
|
|
}
|
|
}
|
|
|
|
void MetaCoreSceneRenderer::RenderScene(const MetaCoreScene& scene, const MetaCoreSceneView& sceneView) const {
|
|
if (Impl_ == nullptr) {
|
|
return;
|
|
}
|
|
|
|
Impl_->LineShader.Bind();
|
|
Impl_->LineShader.SetMatrix4("uView", sceneView.ViewMatrix);
|
|
Impl_->LineShader.SetMatrix4("uProjection", sceneView.ProjectionMatrix);
|
|
Impl_->LineShader.SetMatrix4("uModel", glm::mat4(1.0F));
|
|
Impl_->DebugGeometry.GetGridMesh().Draw();
|
|
Impl_->DebugGeometry.GetAxesMesh().Draw();
|
|
|
|
const glm::vec3 lightDirection = MetaCoreResolveLightDirection(scene);
|
|
const glm::vec3 lightColor = MetaCoreResolveLightColor(scene);
|
|
const float lightIntensity = MetaCoreResolveLightIntensity(scene);
|
|
|
|
Impl_->LitShader.Bind();
|
|
Impl_->LitShader.SetMatrix4("uView", sceneView.ViewMatrix);
|
|
Impl_->LitShader.SetMatrix4("uProjection", sceneView.ProjectionMatrix);
|
|
Impl_->LitShader.SetVector3("uLightDirection", lightDirection);
|
|
Impl_->LitShader.SetVector3("uLightColor", lightColor);
|
|
Impl_->LitShader.SetFloat("uLightIntensity", lightIntensity);
|
|
|
|
for (const MetaCoreGameObject& object : scene.GetGameObjects()) {
|
|
if (!object.MeshRenderer.has_value() || !object.MeshRenderer->Visible) {
|
|
continue;
|
|
}
|
|
|
|
glm::vec3 baseColor = object.MeshRenderer->BaseColor;
|
|
if (object.Id == sceneView.SelectedObjectId) {
|
|
baseColor = glm::mix(baseColor, glm::vec3(1.0F, 0.62F, 0.18F), 0.55F);
|
|
}
|
|
|
|
Impl_->LitShader.SetMatrix4("uModel", MetaCoreBuildTransformMatrix(object.Transform));
|
|
Impl_->LitShader.SetVector3("uBaseColor", baseColor);
|
|
Impl_->DebugGeometry.GetCubeMesh().Draw();
|
|
}
|
|
}
|
|
|
|
} // namespace MetaCore
|