1#include "ReflectionComponent.h"
5#include "Renderer/IRenderer.h"
7#include "Components/Core/RenderComponent.h"
8#include "Components/Core/SceneComponent.h"
10#include "Systems/Core/CameraSystem.h"
11#include "Systems/Core/TransformSystem.h"
17void Cogs::Core::ReflectionComponent::registerType()
20 Field(
Name(
"position"), &ReflectionComponent::position),
21 Field(
Name(
"normal"), &ReflectionComponent::normal),
25 Method(
Name(
"postUpdate"), &ReflectionComponent::postUpdate),
26 Method(
Name(
"initialize"), &ReflectionComponent::initialize),
29 DynamicComponent::registerDerivedType<ReflectionComponent>().setFields(fields).setMethods(methods);
32void Cogs::Core::ReflectionComponent::initialize(Context * context)
34 this->context = context;
39 const float offset = 0.01f;
41 glm::vec4 cameraSpacePlane(
const glm::mat4 & viewMatrix, glm::vec3 position, glm::vec3 normal,
float s)
43 const glm::vec3 offsetPos = position + normal * offset;
45 const glm::vec3 cPos = glm::vec3(viewMatrix * glm::vec4(offsetPos, 1.0f));
46 const glm::vec3 cNormal = glm::normalize(glm::vec3(viewMatrix * glm::vec4(normal, 0.0))) * s;
48 return glm::vec4(cNormal, -glm::dot(cPos, cNormal));
57 glm::mat4 calculateOblique(
const glm::mat4 & projectionMatrix, glm::vec4 clipPlane)
63 glm::vec4 q = glm::inverse(projectionMatrix) * glm::vec4(
64 glm::sign(clipPlane.x),
65 glm::sign(clipPlane.y),
69 glm::vec4 c = clipPlane * (2.0f / (glm::dot(clipPlane, q)));
71 glm::mat4 output = projectionMatrix;
73 output[0][2] = c.x - projectionMatrix[0][3];
74 output[1][2] = c.y - projectionMatrix[1][3];
75 output[2][2] = c.z - projectionMatrix[2][3];
76 output[3][2] = c.w - projectionMatrix[3][3];
81 glm::mat4 calculateReflectionPlane(glm::vec4 plane)
85 r[0][0] = 1 - 2 * plane.x * plane.x;
86 r[0][1] = -2 * plane.x * plane.y;
87 r[0][2] = -2 * plane.x * plane.z;
90 r[1][0] = -2 * plane.x * plane.y;
91 r[1][1] = 1 - 2 * plane.y * plane.y;
92 r[1][2] = -2 * plane.z * plane.y;
95 r[2][0] = -2 * plane.x * plane.z;
96 r[2][1] = -2 * plane.y * plane.z;
97 r[2][2] = 1 - 2 * plane.z * plane.z;
100 r[3][0] = -2 * plane.w * plane.x;
101 r[3][1] = -2 * plane.w * plane.y;
102 r[3][2] = -2 * plane.w * plane.z;
109void Cogs::Core::ReflectionComponent::postUpdate()
111 if (!context || !texture)
return;
113 const CameraComponent* parentCamera =
nullptr;
114 auto parent = getComponent<SceneComponent>()->parent;
115 if (
auto * parentContainer = parent.resolve(); parentContainer) {
116 parentCamera = parentContainer->getComponent<CameraComponent>();
119 parentCamera = context->cameraSystem->getMainCamera();
121 const auto & parentCameraData = context->cameraSystem->getData(parentCamera);
125 auto cameraComponent = getComponent<CameraComponent>();
126 cameraComponent->enableClippingPlaneAdjustment =
false;
127 cameraComponent->renderTexture = texture;
129 auto & cameraData = context->cameraSystem->getData(cameraComponent);
130 cameraData.passOptions = &passOptions;
132 cameraData.layerMask = cameraData.layerMask & ~(RenderLayers::Ocean | RenderLayers::Annotations | RenderLayers::Overlay);
134 const float d = -glm::dot(normal, position) - offset;
135 const glm::vec4 reflectionPlane(normal, d);
137 bool below = glm::dot(reflectionPlane, cameraData.inverseViewMatrix[3]) < 0.f;
139 const auto reflectionMatrix = below ? glm::mat4() : calculateReflectionPlane(reflectionPlane);
141 cameraData.viewportSize = cameraComponent->viewportSize;
142 cameraData.viewportOrigin = cameraComponent->viewportOrigin;
143 cameraData.viewMatrix = cameraData.viewMatrix * reflectionMatrix;
144 cameraData.inverseViewMatrix = glm::inverse(cameraData.viewMatrix);
145 cameraData.reflection =
true;
146 cameraData.flipWindingOrder = !below;
148 const glm::vec4 clipPlane = cameraSpacePlane(cameraData.viewMatrix, glm::vec3(0.0f), normal, 1.0f);
150 cameraData.rawProjectionMatrix = calculateOblique(parentCameraData.rawProjectionMatrix, clipPlane);
151 cameraData.projectionMatrix = context->renderer->getProjectionMatrix(cameraData.rawProjectionMatrix);
152 cameraData.viewProjection = cameraData.projectionMatrix * cameraData.viewMatrix;
153 cameraData.inverseViewProjectionMatrix = glm::inverse(cameraData.viewProjection);
154 cameraData.frustum = Geometry::calculateFrustum<Geometry::Frustum, glm::mat4>(cameraData.viewProjection);
155 cameraData.renderPass = RenderPass::Reflection;
157 cameraData.discardThreshold = parentCameraData.discardThreshold;
158 cameraData.keepThreshold = parentCameraData.keepThreshold;
Field definition describing a single data member of a data structure.
Simple method definition.
Contains reflection support.
Represents an unique name.