3#include "ProceduralSkyComponent.h"
6#include "EntityStore.h"
7#include "Resources/MeshManager.h"
8#include "Resources/MaterialManager.h"
9#include "Components/Core/MeshRenderComponent.h"
10#include "Systems/Core/MeshSystem.h"
15static const float EARTH_RADIUS = 10000;
16static const float EARTH_ATMOSPHERE_RADIUS = EARTH_RADIUS * 1.025f;
20 float fRayleighScatteringConstant = 0.0025f;
21 float fMieScatteringConstant = 0.0015f;
22 float fSunBrightness = 15.0f;
23 float fRayleighScaleDepth = 0.25f;
24 float fMiePhaseAsymmetryFactor = -0.98f;
25 glm::vec3 vWaveLength = glm::vec3(0.680f, 0.550f, 0.475f);
28float toRadian(
float _x)
30 return _x * 0.017453292519f;
33float lerp(
float _x1,
float _x2,
float _w)
35 return (_x1 + _w * (_x2 - _x1));
38float truncate(
float a_Value,
float a_Min,
float a_Max)
40 if (a_Value < a_Min)
return a_Min;
41 if (a_Value > a_Max)
return a_Max;
46void createSkyDomeMesh(std::vector<Cogs::Core::PositionNormalVertex>& vertices, std::vector<unsigned int>& indices,
int a_nStacks,
int a_nSlices,
float a_fRadius,
float a_fDistribution)
49 for (
auto nStackNumber = 0; nStackNumber <= a_nStacks; nStackNumber++)
51 for (
auto nSliceNumber = 0; nSliceNumber < a_nSlices; nSliceNumber++)
53 auto fTheta = powf((
float)nStackNumber / (
float)a_nStacks, a_fDistribution) * glm::pi<float>();
54 auto fPhi = (float)nSliceNumber / (
float)a_nSlices * glm::pi<float>() * 2.0f;
55 auto fSinTheta = sinf(fTheta);
56 auto fSinPhi = sinf(fPhi);
57 auto fCosTheta = cosf(fTheta);
58 auto fCosPhi = cosf(fPhi);
59 auto pos = glm::vec3(fSinPhi * fSinTheta * a_fRadius, fCosPhi * fSinTheta * a_fRadius, fCosTheta * a_fRadius);
60 auto n = glm::normalize(-pos);
61 vertices.push_back({ pos, n });
66 for (
auto nStackNumber = 0; nStackNumber < a_nStacks; nStackNumber++)
68 for (
auto nSliceNumber = 0; nSliceNumber <= a_nSlices; nSliceNumber++)
70 auto nIndexA = (nStackNumber * a_nSlices) + (nSliceNumber % a_nSlices);
71 auto nIndexB = ((nStackNumber + 1) * a_nSlices) + (nSliceNumber % a_nSlices);
72 indices.push_back(nIndexA);
73 indices.push_back(nIndexB);
78void Cogs::Core::ProceduralSkyComponent::registerType()
81 Field(
Name(
"sunDirection"), &ProceduralSkyComponent::sunDirection)
85 Method(
Name(
"initialize"), &ProceduralSkyComponent::initialize),
86 Method(
Name(
"update"), &ProceduralSkyComponent::update),
89 DynamicComponent::registerDerivedType<ProceduralSkyComponent>()
94void Cogs::Core::ProceduralSkyComponent::initialize(Context * ctx)
98 auto meshEntity = context->store->createChildEntity(
"MeshPart", getContainer(),
"Skydome");
100 auto meshComp = meshEntity->getComponent<MeshComponent>();
103 meshComp->meshHandle = context->meshManager->create();
107 auto materialHandle = context->materialManager->loadMaterial(
"ProceduralSkyMaterial.material");
108 context->materialManager->processLoading();
110 material = materialHandle.resolve();
111 auto materialInstance = context->materialInstanceManager->createMaterialInstance(MaterialHandle(material));
113 auto meshRenderComp = meshEntity->getComponent<MeshRenderComponent>();
114 meshRenderComp->material = materialInstance;
115 meshRenderComp->setChanged();
117 krKmMaterialPropertyKey = material->getVec4Key(
"g_vKrKm");
118 scaleMaterialPropertyKey = material->getVec3Key(
"g_vScale");
119 invWavelengthMaterialPropertyKey = material->getVec3Key(
"g_vInvWavelength");
120 miePhaseAsymmetryFactorMaterialPropertyKey = material->getVec2Key(
"g_fMiePhaseAsymmetryFactor");
121 cameraPos_HeightMaterialPropertyKey = material->getVec4Key(
"g_vCameraPos_Height");
122 sunDirectionMaterialPropertyKey = material->getVec3Key(
"g_vSunDirection");
125 auto mesh = context->meshManager->get(meshEntity->getComponent<MeshComponent>()->meshHandle);
128 std::vector<PositionNormalVertex> vertices;
129 std::vector<unsigned int> indices;
130 createSkyDomeMesh(vertices, indices, 50, 25, EARTH_ATMOSPHERE_RADIUS, 20.0f);
132 mesh->setVertexData(vertices.data(), vertices.size());
133 mesh->setIndexes(std::move(indices));
136void Cogs::Core::ProceduralSkyComponent::update()
140 glm::vec3 vInvWavelength;
141 auto fMiePhaseAsymmetryFactor = getAtmosphericScatteringData(vKrKm, vScale, vInvWavelength);
143 material->setVec4Property(krKmMaterialPropertyKey, vKrKm);
144 material->setVec3Property(scaleMaterialPropertyKey, vScale);
145 material->setVec3Property(invWavelengthMaterialPropertyKey, vInvWavelength);
146 material->setVec2Property(miePhaseAsymmetryFactorMaterialPropertyKey, glm::vec2(fMiePhaseAsymmetryFactor, fMiePhaseAsymmetryFactor * fMiePhaseAsymmetryFactor));
147 material->setVec4Property(cameraPos_HeightMaterialPropertyKey, glm::vec4(0.0f, EARTH_RADIUS, 0.0f, EARTH_RADIUS));
148 material->setVec3Property(sunDirectionMaterialPropertyKey, sunDirection);
151float Cogs::Core::ProceduralSkyComponent::getSunBrightness()
153 static const float s_fAngle95 = toRadian(95.0f);
154 static const float s_fInvAngle20 = 1.0f / toRadian(20.0f);
155 const glm::vec3& vSunDirection = sunDirection;
156 float fAngle = truncate((s_fAngle95 - acosf(vSunDirection.y)) * s_fInvAngle20, 0.0f, 1.0f);
158 return powf(fAngle, 1.0f / 1.5f);
161float Cogs::Core::ProceduralSkyComponent::getAtmosphericScatteringData(glm::vec4& vKrKm, glm::vec3& vScale, glm::vec3& vInvWavelength)
165 const float fKr = lerp(0.0075f, cAtmosphericScattering.fRayleighScatteringConstant, getSunBrightness());
166 const float fKr4PI = fKr * 4.0f * glm::pi<float>();
167 const float fKm = cAtmosphericScattering.fMieScatteringConstant;
168 const float fKm4PI = fKm * 4.0f * glm::pi<float>();
169 const float fKrESun = fKr * cAtmosphericScattering.fSunBrightness;
170 const float fKmESun = fKm * cAtmosphericScattering.fSunBrightness;
171 vKrKm = glm::vec4(fKrESun, fKmESun, fKr4PI, fKm4PI);
173 const float fScale = 1.0f / (EARTH_ATMOSPHERE_RADIUS - EARTH_RADIUS);
174 const float fScaleDepth = cAtmosphericScattering.fRayleighScaleDepth;
175 const float fScaleOverScaleDepth = fScale / cAtmosphericScattering.fRayleighScaleDepth;
176 vScale = glm::vec3(fScale, fScaleDepth, fScaleOverScaleDepth);
178 vInvWavelength.x = 1.0f / powf(cAtmosphericScattering.vWaveLength.x, 4.0f);
179 vInvWavelength.y = 1.0f / powf(cAtmosphericScattering.vWaveLength.y, 4.0f);
180 vInvWavelength.z = 1.0f / powf(cAtmosphericScattering.vWaveLength.z, 4.0f);
182 return cAtmosphericScattering.fMiePhaseAsymmetryFactor;
Field definition describing a single data member of a data structure.
Simple method definition.
Contains geometry calculations and generation.
Contains reflection support.
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.
@ TriangleStrip
Triangle strip.
Represents an unique name.