1#include "Rendering/IGraphicsDevice.h"
2#include "Rendering/ICapabilities.h"
3#include "Foundation/Logging/Logger.h"
5#include "BasicOceanSystem.h"
7#include "Components/Appearance/MaterialComponent.h"
8#include "Components/Geometry/AdaptivePlanarGridComponent.h"
9#include "Components/Core/SceneComponent.h"
10#include "Components/Core/CameraComponent.h"
11#include "Components/Behavior/ReflectionComponent.h"
13#include "Systems/Core/TransformSystem.h"
14#include "Systems/Geometry/AdaptivePlanarGridSystem.h"
16#include "Resources/MaterialManager.h"
17#include "Resources/TextureManager.h"
18#include "Resources/Texture.h"
20#include "Services/Variables.h"
21#include "Services/Time.h"
22#include "Services/TaskManager.h"
24#include "EntityStore.h"
26#include "Utilities/Parsing.h"
30#define _USE_MATH_DEFINES
39#if !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
47 const std::string animateKey =
"basic-ocean.animate";
48 const std::string eightbitKey =
"basic-ocean.8bit";
53 assert(oceanData->waveVariant !=
nullptr);
54 instance->setVariant(
"Encoding", oceanData->encoding);
55 instance->setVariant(
"Waves", oceanData->waveVariant);
56 instance->setVariant(
"BeliefSystem", oceanData->beliefSystem);
57 instance->setVariant(
"LightModel", oceanData->lightModelVariant);
58 instance->setVariant(
"Reflection", oceanData->reflectionVariant);
64 inline size_t reverseBits16(
size_t i,
size_t log2N)
69 t = ((0xAAAAu & t) >> 1) | ((t << 1) & 0xAAAAu);
70 t = ((0xCCCCu & t) >> 2) | ((t << 2) & 0xCCCCu);
71 t = ((0xF0F0u & t) >> 4) | ((t << 4) & 0xF0F0u);
72 t = ((0xFF00u & t) >> 8) | ((t << 8) & 0xFF00u);
73 return t >> (16 - log2N);
77 const float twoPi = float(2.0 * M_PI);
79 inline complex<float> twiddleFactor(
const int n,
const int N)
81 const float arg = (-twoPi * float(n)) /
float(N);
82 return complex<float>(cos(arg), sin(arg));
87#if !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
88 void inverseRadix2MajorIndexTransposeAlignedSoALog4SSE1(
float* dstReal,
96 size_t N = size_t(1) << log2N;
100 for (
size_t j = 0; j < N / 2; j++) {
101 size_t index0 = 2 * j;
102 size_t index1 = index0 + 1;
103 size_t reversedIndex0 = reverseBits16(index0, log2N);
104 size_t reversedIndex1 = reverseBits16(index1, log2N);
105 __m128 mm_scale = _mm_set1_ps(scale);
106 for (
size_t i = 0; i < Nq; i++) {
107 size_t srcIx0 = (4 * i * N + reversedIndex0);
108 __m128 aReal02 = _mm_unpacklo_ps(_mm_load_ss(srcReal + srcIx0 + 0 * N), _mm_load_ss(srcReal + srcIx0 + 2 * N));
109 __m128 aReal13 = _mm_unpacklo_ps(_mm_load_ss(srcReal + srcIx0 + 1 * N), _mm_load_ss(srcReal + srcIx0 + 3 * N));
110 __m128 aReal = _mm_mul_ps(mm_scale, _mm_unpacklo_ps(aReal02, aReal13));
112 __m128 aImag02 = _mm_unpacklo_ps(_mm_load_ss(srcImag + srcIx0 + 0 * N), _mm_load_ss(srcImag + srcIx0 + 2 * N));
113 __m128 aImag13 = _mm_unpacklo_ps(_mm_load_ss(srcImag + srcIx0 + 1 * N), _mm_load_ss(srcImag + srcIx0 + 3 * N));
114 __m128 aImag = _mm_mul_ps(mm_scale, _mm_unpacklo_ps(aImag02, aImag13));
116 size_t srcIx1 = (4 * i * N + reversedIndex1);
117 __m128 bReal02 = _mm_unpacklo_ps(_mm_load_ss(srcReal + srcIx1 + 0 * N), _mm_load_ss(srcReal + srcIx1 + 2 * N));
118 __m128 bReal13 = _mm_unpacklo_ps(_mm_load_ss(srcReal + srcIx1 + 1 * N), _mm_load_ss(srcReal + srcIx1 + 3 * N));
119 __m128 bReal = _mm_mul_ps(mm_scale, _mm_unpacklo_ps(bReal02, bReal13));
121 __m128 bImag02 = _mm_unpacklo_ps(_mm_load_ss(srcImag + srcIx1 + 0 * N), _mm_load_ss(srcImag + srcIx1 + 2 * N));
122 __m128 bImag13 = _mm_unpacklo_ps(_mm_load_ss(srcImag + srcIx1 + 1 * N), _mm_load_ss(srcImag + srcIx1 + 3 * N));
123 __m128 bImag = _mm_mul_ps(mm_scale, _mm_unpacklo_ps(bImag02, bImag13));
125 __m128 pReal = _mm_add_ps(aReal, bReal);
126 __m128 pImag = _mm_add_ps(aImag, bImag);
127 size_t dstIx0 = (index0 * N + 4 * i);
128 _mm_store_ps(dstReal + dstIx0, pReal);
129 _mm_store_ps(dstImag + dstIx0, pImag);
131 __m128 qReal = _mm_sub_ps(aReal, bReal);
132 __m128 qImag = _mm_sub_ps(aImag, bImag);
133 size_t dstIx1 = (index1 * N + 4 * i);
134 _mm_store_ps(dstReal + dstIx1, qReal);
135 _mm_store_ps(dstImag + dstIx1, qImag);
140 for (
size_t l = 1; l < log2N; l++) {
141 int blockSize = 2 << l;
142 for (
size_t j = 0; j < N / 2; j++) {
143 size_t blockNumber = j >> l;
144 size_t blockIndex = j & ((1 << l) - 1);
145 size_t index0 = (blockSize * blockNumber + blockIndex);
146 size_t index1 = (index0 + blockSize / 2);
147 float* real0 = dstReal + index0 * N;
148 float* imag0 = dstImag + index0 * N;
149 float* real1 = dstReal + index1 * N;
150 float* imag1 = dstImag + index1 * N;
152 int twiddleIndex = int(blockIndex << (log2N - l - 1));
153 const float twiddleArg = (factor * twiddleIndex) / N;
154 __m128 wReal = _mm_set1_ps(cos(twiddleArg));
155 __m128 wImag = _mm_set1_ps(sin(twiddleArg));
156 for (
size_t i = 0; i < Nq; i++) {
157 __m128 aReal = _mm_load_ps(real0);
158 __m128 bReal = _mm_load_ps(real1);
160 __m128 aImag = _mm_load_ps(imag0);
161 __m128 bImag = _mm_load_ps(imag1);
163 __m128 cReal = _mm_sub_ps(_mm_mul_ps(wReal, bReal), _mm_mul_ps(wImag, bImag));
164 __m128 cImag = _mm_add_ps(_mm_mul_ps(wReal, bImag), _mm_mul_ps(wImag, bReal));
166 _mm_store_ps(real0, _mm_add_ps(aReal, cReal)); real0 += 4;
167 _mm_store_ps(imag0, _mm_add_ps(aImag, cImag)); imag0 += 4;
169 _mm_store_ps(real1, _mm_sub_ps(aReal, cReal)); real1 += 4;
170 _mm_store_ps(imag1, _mm_sub_ps(aImag, cImag)); imag1 += 4;
177 void inverseRadix2MajorIndexTranspose(
float* dstReal,
179 const size_t dstStride,
180 const float* srcReal,
181 const float* srcImag,
182 const size_t srcStride,
187 size_t N = (size_t)1 << log2N;
190 for (
size_t j = 0; j < N / 2; j++) {
191 size_t index0 = 2 * j;
192 size_t index1 = index0 + 1;
193 size_t reversedIndex0 = reverseBits16(index0, log2N);
194 size_t reversedIndex1 = reverseBits16(index1, log2N);
195 for (
size_t i = 0; i < N; i++) {
196 size_t srcIx0 = srcStride * (i * N + reversedIndex0);
197 size_t srcIx1 = srcStride * (i * N + reversedIndex1);
198 size_t dstIx0 = dstStride * (index0 * N + i);
199 size_t dstIx1 = dstStride * (index1 * N + i);
200 complex<float> a = scale * complex<float>(srcReal[srcIx0], srcImag[srcIx0]);
201 complex<float> b = scale * complex<float>(srcReal[srcIx1], srcImag[srcIx1]);
202 complex<float> p = a + b;
203 complex<float> q = a - b;
204 dstReal[dstIx0] = p.real(); dstImag[dstIx0] = p.imag();
205 dstReal[dstIx1] = q.real(); dstImag[dstIx1] = q.imag();
210 for (
size_t l = 1; l < log2N; l++) {
211 int blockSize = 2 << l;
212 for (
size_t j = 0; j < N / 2; j++) {
213 size_t blockNumber = j >> l;
214 size_t blockIndex = j & ((1 << l) - 1);
215 size_t index0 = (blockSize * blockNumber + blockIndex);
216 size_t index1 = (index0 + blockSize / 2);
217 int twiddleIndex = int(blockIndex << (log2N - l - 1));
218 const float twiddleArg = (factor * twiddleIndex) / N;
219 complex<float> w(cos(twiddleArg), sin(twiddleArg));
220 for (
size_t i = 0; i < N; i++) {
221 size_t srcDstIx0 = dstStride * (index0 * N + i);
222 size_t srcDstIx1 = dstStride * (index1 * N + i);
223 complex<float> a = complex<float>(dstReal[srcDstIx0], dstImag[srcDstIx0]);
224 complex<float> b = complex<float>(dstReal[srcDstIx1], dstImag[srcDstIx1]);
225 complex<float> c = w * b;
226 complex<float> p = a + c;
227 complex<float> q = a - c;
228 dstReal[srcDstIx0] = p.real(); dstImag[srcDstIx0] = p.imag();
229 dstReal[srcDstIx1] = q.real(); dstImag[srcDstIx1] = q.imag();
240 const size_t dstStride,
241 const uint8_t* srcReal,
242 const uint8_t* srcImag,
243 const size_t srcStride,
249 assert((
reinterpret_cast<size_t>(dstReal) & 0x3) == 0);
250 assert((
reinterpret_cast<size_t>(dstImag) & 0x3) == 0);
251 assert((
reinterpret_cast<size_t>(srcReal) & 0x3) == 0);
252 assert((
reinterpret_cast<size_t>(srcImag) & 0x3) == 0);
253 assert((dstStride & 0x3) == 0);
254 assert((srcStride & 0x3) == 0);
256 float* scratchf =
reinterpret_cast<float*
>(32 * ((
reinterpret_cast<size_t>(scratch) + 31) / 32));
257 float* dstRealf =
reinterpret_cast<float*
>(dstReal);
258 float* dstImagf =
reinterpret_cast<float*
>(dstImag);
259 const float* srcRealf =
reinterpret_cast<const float*
>(srcReal);
260 const float* srcImagf =
reinterpret_cast<const float*
>(srcImag);
261 size_t dstStridef = dstStride /
sizeof(float);
262 size_t srcStridef = srcStride /
sizeof(float);
264#if !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
265 size_t N = size_t(1) << log2N;
270 ((
reinterpret_cast<size_t>(dstReal) & 0xf) == 0) &&
271 ((
reinterpret_cast<size_t>(dstImag) & 0xf) == 0) &&
272 ((
reinterpret_cast<size_t>(srcReal) & 0xf) == 0) &&
273 ((
reinterpret_cast<size_t>(srcImag) & 0xf) == 0))
275 inverseRadix2MajorIndexTransposeAlignedSoALog4SSE1(scratchf, scratchf + N * N,
277 factor, scale, log2N);
279 inverseRadix2MajorIndexTransposeAlignedSoALog4SSE1(dstRealf, dstImagf,
280 scratchf, scratchf + N * N,
286 inverseRadix2MajorIndexTranspose(scratchf, scratchf + 1, 2,
287 srcRealf, srcImagf, srcStridef,
288 factor, scale, log2N);
290 inverseRadix2MajorIndexTranspose(dstRealf, dstImagf, dstStridef,
291 scratchf, scratchf + 1, 2,
305 inline size_t fastGenericFourierTransform2DScratchsize(
size_t log2N) {
return sizeof(float) * (
size_t(2) << (log2N << 1)) + 64; }
309 std::vector<uint8_t>& scratch,
315 CpuInstrumentationScope(SCOPE_GEOMETRY,
"OceanSystem::fastInverseFourierTransform2D");
317 scratch.resize(fastGenericFourierTransform2DScratchsize(log2N));
318 fastGenericFourierTransform2D(context,
319 reinterpret_cast<uint8_t*
>(scratch.data()),
320 reinterpret_cast<uint8_t*
>(dst.real()),
321 reinterpret_cast<uint8_t*
>(dst.imag()),
323 reinterpret_cast<const uint8_t*
>(src.real()),
324 reinterpret_cast<const uint8_t*
>(src.imag()),
326 float(2.0 * 3.14159265358979323846),
466 const float pi = std::acos(-1.f);
468 const float twoPi = float(2.0 * glm::pi<float>());
470 const float g = 9.80665f;
472 float waveSpectrumPhillips(
const float omega,
473 const float alpha = 0.0081f)
475 const float omega2 = omega * omega;
476 const float omega4 = omega2 * omega2;
477 const float omega5 = omega4 * omega;
479 return (alpha * g * g) / omega5;
482 float waveSpectrumPiersonMoskowitz(
const float omega,
484 const float alpha = 0.0081f)
486 const float omega_p_over_omega = omega_p / omega;
487 const float omega_p_over_omega4 = (omega_p_over_omega * omega_p_over_omega) * (omega_p_over_omega * omega_p_over_omega);
489 return waveSpectrumPhillips(omega, alpha) * exp(
float(-5.0 / 4.0) * omega_p_over_omega4);
492 float dispersionLonguetHiggins(
const float omega,
495 const float windWaveAngle)
499 float mu = omega <= omega_p ? 5.f : -2.5f;
500 float s_omega = 11.5f * pow(g / (omega_p * U10), 2.5f) * pow(omega / omega_p, mu);
501 assert(std::isfinite(s_omega));
515 float J = s_omega + 0.5f;
516 float gammaRatio = sqrt(J) * (1.f - 1.f / (8.f * J) + 1.f / (128.f * J * J) + 5.f / (1024.f * J * J * J) - 21.f / (32768.f * J * J * J * J));
517 float N_s_omega = float(1.0 / (2.0 * sqrt(glm::pi<float>()))) * (gammaRatio);
518 assert(std::isfinite(N_s_omega));
526 float D = N_s_omega * pow(max(0.0f, cos(0.5f * windWaveAngle)), 2.f * s_omega);
527 assert(std::isfinite(D));
533 void createDirectionalWaveSpectrum(std::vector<float>& E,
540 float dominantWavePeriod)
542 if (windDirection >= pi) {
543 windDirection -= twoPi;
545 if (windSpeed < 2.f) {
549 float dominantAngularVelocity = float(2.0 * glm::pi<float>()) / dominantWavePeriod;
552 glm::vec2 windDir(glm::cos(windDirection), glm::sin(windDirection));
554 for (
size_t j = 0; j < N; j++) {
555 for (
size_t i = 0; i < N; i++) {
556 if ((i == 0) && (j == 0)) {
561 ivec2 ij(i <= N / 2 ?
int(i) :
int(i) -
int(N),
562 j <= N / 2 ?
int(j) :
int(j) -
int(N));
564 const vec2 K = (twoPi / L) * vec2(ij);
566 float angularVelocity = sqrt(g * k);
569 float cosWindWaveAngle = std::max(-1.f, std::min(1.f, (1.f / k) * dot(K, windDir)));
570 float windWaveAngle = std::acos(cosWindWaveAngle);
571 assert(std::isfinite(windWaveAngle));
573 const float S = waveSpectrumPiersonMoskowitz(angularVelocity,
574 dominantAngularVelocity,
576 const float D = dispersionLonguetHiggins(angularVelocity,
577 dominantAngularVelocity,
581 const float chainFactor = (1.f / (2.f * k)) * sqrt(g / k);
583 sumS += chainFactor * S;
584 E[N * j + i] = chainFactor * S * D;
590 float w = 1.f / sumS;
591 for (
size_t i = 0; i < N * N; i++) {
598 const std::vector<float>& E,
599 const unsigned int seed,
602 std::minstd_rand eng(seed);
603 std::uniform_int_distribution<int> dist(0, RAND_MAX);
605 for (
size_t j = 0; j < N; j++) {
606 for (
size_t i = 0; i < N; i++) {
610 for (
int q = 0; q < 12; q++) {
611 eta0 += float(dist(eng)) / float(RAND_MAX);
612 eta1 += float(dist(eng)) / float(RAND_MAX);
616 H.store(N * j + i, sqrt(E[N * j + i] / 2.f) * std::complex<float>(eta0, eta1));
621 float U0 = float(dist(eng) + 1) / (float(RAND_MAX) + 2);
622 float U1 = (2.f * float(glm::pi<float>())) * (
float(dist(eng)) / (float(RAND_MAX) + 1));
625 complex<float> eta = sqrt(-2.f *
log(U0)) * complex<float>(cos(U1), sin(U1));
627 H.store(N * j + i, sqrt(E[N * j + i] / 2.f) * eta);
633 void fastSinCos(
float& sin,
float& cos,
const float x)
635 float r = (2.0f / glm::pi<float>()) * x;
641 float vx = x_ * x_ * (x_ * (2.f - 33.f / 20.f) + (33.f / 20.f - 3.f)) + 1.f;
642 float vy = y_ * y_ * (y_ * (2.f - 33.f / 20.f) + (33.f / 20.f - 3.f)) + 1.f;
644 float c = ((k & 1) == 0) ? vx : vy;
645 float s = ((k & 1) == 0) ? vy : vx;
647 cos = (((k + 1) & 2) == 0) ? c : -c;
648 sin = ((k & 2) == 0) ? s : -s;
651 complex<float> fastPolar(
float rho,
float theta)
655 fastSinCos(sin, cos, theta);
657 return complex<float>(rho * cos, rho * sin);
672 for (
size_t j = start; j < end; j++) {
673 for (
size_t i = 0; i < N; i++) {
674 const vec2 K = (twoPi / L) * vec2(i <= N / 2 ?
int(i) : int(i) - int(N),
675 j <= N / 2 ? int(j) : int(j) - int(N));
677 vec2 kn = (1.f / k) * K;
678 float omega = sqrt(g * k);
680 complex<float> A = a.load(N * j + i) * fastPolar(1.f, omega * t);
682 dZdu.store(N * j + i, K.x * A);
683 dZdv.store(N * j + i, K.y * A);
684 Ax.store(N * j + i, kn.x * A);
685 Ay.store(N * j + i, kn.y * A);
686 Az.store(N * j + i, A);
689 dZdu.store(0, complex<float>(0.f));
690 dZdv.store(0, complex<float>(0.f));
691 Ax.store(0, complex<float>(0.f));
692 Ay.store(0, complex<float>(0.f));
693 Az.store(0, complex<float>(0.f));
696 void encodeTextureData(vec4* tangents,
707 for (
size_t i = begin; i < end; i++) {
710 glm::vec3 re = glm::vec3(Dx.load(ix).real(), Dy.load(ix).real(), Dz.load(ix).real());
711 glm::vec3 im = glm::vec3(Dx.load(ix).imag(), Dy.load(ix).imag(), Dz.load(ix).imag());
712 glm::vec4 ta = glm::vec4(dZdu.load(ix).real(), dZdu.load(ix).imag(), dZdv.load(ix).real(), dZdv.load(ix).imag());
714 real[ix] = vec4(re, 0.f);
715 imag[ix] = vec4(im, 0.f);
720 void encodeTextureDataTangents(glm::u8vec4* tangents,
722 float& magnitude0Out,
723 float& magnitude1Out,
729 const float magnitude0In,
730 const float magnitude1In,
734 const float scale0 = 0.5f * 255.f / magnitude0In;
735 const float scale1 = 0.5f * 255.f / magnitude1In;
737 float magnitude0 = 0.f;
738 float magnitude1 = 0.f;
739 for (
size_t i = begin; i < end; i++) {
742 glm::vec3 re = glm::vec3(Dx.load(ix).real(), Dy.load(ix).real(), Dz.load(ix).real());
743 glm::vec3 im = glm::vec3(Dx.load(ix).imag(), Dy.load(ix).imag(), Dz.load(ix).imag());
744 glm::vec4 ta = glm::vec4(dZdu.load(ix).real(), dZdu.load(ix).imag(), dZdv.load(ix).real(), dZdv.load(ix).imag());
746 magnitude0 = std::max(std::max(std::max(std::abs(re.x), std::abs(re.y)),
747 std::max(std::abs(re.z), std::abs(im.x))),
748 std::max(std::max(std::abs(im.y), std::abs(im.z)),
751 magnitude1 = std::max(std::max(std::max(std::abs(ta.x), std::abs(ta.y)),
752 std::max(std::abs(ta.z), std::abs(ta.w))),
755 real[ix] = vec4(glm::clamp(scale0 * (re + glm::vec3(magnitude0In)), glm::vec3(0.f), glm::vec3(255.f)), 0.f);
756 tangents[ix] = glm::clamp(scale1 * (ta + vec4(magnitude1In)), glm::vec4(0.f), glm::vec4(255.f));
758 magnitude0Out = magnitude0;
759 magnitude1Out = magnitude1;
763 void encodeTextureDataQuux(vec4* pos,
771 const float significantWaveHeight,
776 const size_t N = (size_t)1 << m;
777 const auto M = N - 1;
778 const auto s = 1.f / L;
779 const auto l = L / N;
780 const auto h = significantWaveHeight;
810 for (
size_t j = begin; j < end; j++) {
811 size_t jp = (j + 1) & M;
813 for (
size_t i = 0; i < N; i++) {
814 size_t ip = (i + 1) & M;
816 float x = Dx.load((j << m) + i).imag();
817 float y = Dy.load((j << m) + i).imag();
818 float z = -Dz.load((j << m) + i).real();
820 float dx_du = l * (Dx.load((j << m) + ip).imag() - x);
821 float dy_du = l * (Dy.load((j << m) + ip).imag() - y);
823 float dx_dv = l * (Dx.load((jp << m) + i).imag() - x);
824 float dy_dv = l * (Dy.load((jp << m) + i).imag() - y);
826 float zdu = dZdu.load((j << m) + i).imag();
827 float zdv = dZdv.load((j << m) + i).imag();
829 glm::vec3 u = glm::vec3(s * dx_du + 1.f, s * dy_du + 0.f, h * zdu);
830 glm::vec3 v = glm::vec3(s * dx_dv + 0.f, s * dy_dv + 1.f, h * zdv);
831 glm::vec3 n = glm::normalize(glm::cross(u, v));
833 pos[(j << m) + i] = glm::vec4(x, y, z, 0);
834 nrm[(j << m) + i] = glm::vec4(n.x, n.y, n.z, 0);
840 void encodeTextureDataQuux(glm::u8vec4* pos,
842 float& magnitude0Out,
843 float& magnitude1Out,
849 const float magnitude0In,
850 const float magnitude1In,
852 const float significantWaveHeight,
857 float magnitude0 = 0.f;
858 float magnitude1 = 0.f;
859 const size_t N = (size_t)1 << m;
860 const auto M = N - 1;
861 const auto s = 1.f / L;
862 const auto l = L / N;
863 const auto h = significantWaveHeight;
865 const float scale0 = 0.5f * 255.f / magnitude0In;
866 const float scale1 = 0.5f * 255.f / magnitude1In;
867 for (
size_t j = begin; j < end; j++) {
868 size_t jp = (j + 1) & M;
870 for (
size_t i = 0; i < N; i++) {
871 size_t ip = (i + 1) & M;
873 glm::vec3 p = glm::vec3(Dx.load((j << m) + i).imag(),
874 Dy.load((j << m) + i).imag(),
875 -Dz.load((j << m) + i).real());
877 float dx_du = l * (Dx.load((j << m) + ip).imag() - p.x);
878 float dy_du = l * (Dy.load((j << m) + ip).imag() - p.y);
880 float dx_dv = l * (Dx.load((jp << m) + i).imag() - p.x);
881 float dy_dv = l * (Dy.load((jp << m) + i).imag() - p.y);
883 float zdu = dZdu.load((j << m) + i).imag();
884 float zdv = dZdv.load((j << m) + i).imag();
886 glm::vec3 u = glm::vec3(s * dx_du + 1.f, s * dy_du + 0.f, h * zdu);
887 glm::vec3 v = glm::vec3(s * dx_dv + 0.f, s * dy_dv + 1.f, h * zdv);
888 glm::vec3 n = glm::normalize(glm::cross(u, v));
890 magnitude0 = std::max(std::max(std::abs(p.x), std::abs(p.y)),
891 std::max(std::abs(p.z), magnitude0));
895 magnitude1 = std::max(std::max(std::abs(n.x), std::abs(n.y)),
896 std::max(std::abs(n.z - 1.f), magnitude1));
898 pos[(j << m) + i] = glm::vec4(glm::clamp(scale0 * (p + glm::vec3(magnitude0In)), glm::vec3(0.f), glm::vec3(255.f)), 0);
899 nrm[(j << m) + i] = glm::vec4(glm::clamp(scale1 * glm::vec3(n.x + magnitude1In,
901 n.z - 1.f), glm::vec3(0.f), glm::vec3(255.f)), 0);
904 magnitude0Out = magnitude0;
905 magnitude1Out = magnitude1;
918 DisplacementTexH =
context->textureManager->create();
919 NormalTexH =
context->textureManager->create();
920 TangentsTexH =
context->textureManager->create();
922 DisplacementTexH->
setName(
"BasicOcean.Displacement");
923 NormalTexH->
setName(
"BasicOcean.Normals");
924 TangentsTexH->
setName(
"BasicOcean.Tangents");
932 if (animateVar->isEmpty()) {
933 animateVar->setBool(
true);
936 if (eightbitVar->isEmpty()) {
937 eightbitVar->setBool(
true);
943 if (oceanTaskGroup.isValid()) {
955void Cogs::Core::BasicOceanSystem::setupMaterial()
957 auto adaptiveMat = context->materialManager->loadMaterial(
"AdaptiveGridMaterial.material");
958 oceanMaterial = context->materialManager->loadMaterial(
"BasicOceanMaterial.material");
959 oceanMaterial2 = context->materialManager->loadMaterial(
"BasicSkyMaterial.material");
963 context->materialManager->processLoading();
967 auto m = oceanMaterial.resolve();
969 DisplacementKey = m->getTextureKey(
"Displacement");
970 NormalKey = m->getTextureKey(
"Difference");
972 TangentsKey = m->getTextureKey(
"Tangents");
974 m->setTextureProperty(DisplacementKey, DisplacementTexH);
975 m->setTextureProperty(NormalKey, NormalTexH);
976 m->setTextureProperty(TangentsKey, TangentsTexH);
978 ReflectionTextureH = context->textureManager->create();
979 ReflectionTextureH->setName(
"BasicOcean.Reflection");
981 PlanarReflectionKey = m->getTextureKey(
"PlanarReflection");
982 m->setTextureProperty(PlanarReflectionKey, ReflectionTextureH);
985 cameraYAxisKey = m->getVec4Key(
"cameraYAxis");
986 waterColorKey = m->getVec4Key(
"waterColor");
987 waveDirectionKey = m->getVec2Key(
"waveDirection");
988 camPlaneDirKey = m->getVec2Key(
"camPlaneDir");
989 significantWaveHeightKey = m->getFloatKey(
"significantWaveHeight");
990 fftTileScaleKey = m->getFloatKey(
"fftTileScale");
991 camAzimuthKey = m->getFloatKey(
"camAzimuth");
992 seaLevelKey = m->getFloatKey(
"seaLevel");
993 reflectionBrightnessKey = m->getFloatKey(
"reflectionBrightness");
994 phaseShiftNoiseFrequencyKey = m->getFloatKey(
"phaseShiftNoiseFrequency");
995 phaseShiftNoisePeriodKey = m->getFloatKey(
"phaseShiftNoisePeriod");
1000 const auto textureResolution =
static_cast<uint32_t
>(std::max(1,context->
variables->get(
"ocean.reflectionTextureResolution", 1024)));
1001 auto reflectionTex = context->textureManager->get(ReflectionTextureH);
1003 TextureFormat format = TextureFormat::R8G8B8A8_UNORM_SRGB;
1004 if (oceanComp !=
nullptr) {
1005 format = parseTextureFormat(oceanComp->reflectionTexFormat, format);
1008 if ((reflectionTex->description.width != textureResolution)
1009 || (reflectionTex->description.format != format))
1011 reflectionTex->description.width = textureResolution;
1012 reflectionTex->description.height = textureResolution;
1013 reflectionTex->description.format = format;
1015 reflectionTex->setChanged();
1019void Cogs::Core::BasicOceanSystem::setupWaveSpectrum()
1021 size_t N = size_t(1) << fftTileResolutionLog2;
1022 size_t N_times_N = N*N;
1024 constexpr float oneOvertwoPi = 1.f / (2.0f * std::numbers::pi_v<float>);
1025 const float dominantWaveLength = oneOvertwoPi*(g*dominantWavePeriod*dominantWavePeriod);
1027 fftTileExtent = dominantWaveLength;
1029 P.resize(N_times_N);
1030 frqH0.resize(N_times_N);
1031 frqDx.resize(N_times_N);
1032 frqDy.resize(N_times_N);
1033 frqDz.resize(N_times_N);
1034 frqdDzdu.resize(N_times_N);
1035 frqdDzdv.resize(N_times_N);
1037 spcDx.resize(N_times_N);
1038 spcDy.resize(N_times_N);
1039 spcDz.resize(N_times_N);
1040 spcdDzdu.resize(N_times_N);
1041 spcdDzdv.resize(N_times_N);
1043 fftScratch.resize(fastGenericFourierTransform2DScratchsize(N_times_N));
1045 const float omega_p = (0.855f*g) / windSpeed;
1047 createDirectionalWaveSpectrum(P, N, fftTileExtent, omega_p, windSpeed, 0.f , 1.f, dominantWavePeriod);
1048 createRandomizedWaveSpectrumInstance(frqH0, P, 42, N);
1051void Cogs::Core::BasicOceanSystem::updateTextures(
const float magnitudeIn0,
const float magnitudeIn1)
1053 CpuInstrumentationScope(SCOPE_SYSTEMS,
"OceanSystem::updateTextures");
1055 const uint16_t N = uint16_t(1) << fftTileResolutionLog2;
1057 auto realTex = context->textureManager->get(DisplacementTexH);
1058 auto imagTex = context->textureManager->get(NormalTexH);
1059 auto tangentsTex = context->textureManager->get(TangentsTexH);
1064 case BasicOceanWaves::Default: M =
static_cast<size_t>(N) * N;
break;
1065 case BasicOceanWaves::Quux: M =
static_cast<size_t>(N);
break;
1066 default: assert(
false &&
"Illegal wave type");
break;
1070 size_t incr = (M + split - 1) / split;
1074 std::vector<float> magnitudes_scratch0(split, 0.f);
1075 std::vector<float> magnitudes_scratch1(split, 0.f);
1080 case BasicOceanWaves::Default:
1083 for (
size_t i = 0; i < split; ++i) {
1084 TaskFunction f = [
this, i, magnitudeIn0, magnitudeIn1, incr, M, &tangents, &real, &magnitudes_scratch0, &magnitudes_scratch1]() {
1085 CpuInstrumentationScope(SCOPE_SYSTEMS,
"OceanSystem::encodeTextureData");
1086 encodeTextureDataTangents(tangents.data(), real.data(), magnitudes_scratch0[i], magnitudes_scratch1[i],
1087 spcdDzdu, spcdDzdv, spcDx, spcDy, spcDz,
1088 magnitudeIn0, magnitudeIn1,
1089 i * incr, std::min(M, (i + 1) * incr));
1091 if (1 < split) { context->
taskManager->enqueueChild(gr, f); }
else { f(); }
1100 case BasicOceanWaves::Quux:
1102 for (
size_t i = 0; i < split; ++i) {
1103 TaskFunction f = [
this, i, magnitudeIn0, magnitudeIn1, incr, M, &real, &imag, &magnitudes_scratch0, &magnitudes_scratch1]() {
1104 CpuInstrumentationScope(SCOPE_SYSTEMS,
"OceanSystem::encodeTextureData");
1105 encodeTextureDataQuux(real.data(), imag.data(), magnitudes_scratch0[i], magnitudes_scratch1[i],
1106 spcdDzdu, spcdDzdv, spcDx, spcDy, spcDz,
1107 magnitudeIn0, magnitudeIn1,
1108 fftTileExtent, significantWaveHeight,
1109 i * incr, std::min(M, (i + 1) * incr),
1110 fftTileResolutionLog2);
1112 if (1 < split) { context->
taskManager->enqueueChild(gr, f); }
else { f(); }
1127 case BasicOceanWaves::Default:
1130 for (
size_t i = 0; i < split; ++i) {
1131 TaskFunction f = [
this, i, incr, M, &tangents, &real, &imag]() {
1132 CpuInstrumentationScope(SCOPE_SYSTEMS,
"OceanSystem::encodeTextureData");
1133 encodeTextureData(tangents.data(), real.data(), imag.data(),
1134 spcdDzdu, spcdDzdv, spcDx, spcDy, spcDz,
1135 i * incr, std::min(M, (i + 1) * incr));
1137 if (1 < split) { context->
taskManager->enqueueChild(gr, f); }
1147 case BasicOceanWaves::Quux:
1148 for (
size_t i = 0; i < split; ++i) {
1150 CpuInstrumentationScope(SCOPE_SYSTEMS,
"OceanSystem::encodeTextureData");
1151 encodeTextureDataQuux(real.data(), imag.data(),
1152 spcdDzdu, spcdDzdv, spcDx, spcDy, spcDz,
1153 fftTileExtent, significantWaveHeight,
1154 i * incr, std::min(M, (i + 1) * incr),
1155 fftTileResolutionLog2);
1157 if (1 < split) { context->
taskManager->enqueueChild(gr, f); }
1171 magnitudes_tmp.channel0 = *std::max_element(magnitudes_scratch0.begin(), magnitudes_scratch0.end());
1172 magnitudes_tmp.channel1 = *std::max_element(magnitudes_scratch1.begin(), magnitudes_scratch1.end());
1176void Cogs::Core::BasicOceanSystem::updateTileMaterialInstances(
const BasicOceanData & oceanData,
1179 const glm::mat4 & viewToWorld,
1180 const glm::vec2 & viewPortSize)
1182 const glm::vec2 camPlaneDir = glm::normalize(glm::vec2(viewToWorld[2]));
1183 float camAzimuth = (0.5f / glm::pi<float>()) * acos(camPlaneDir.x);
1185 if (camPlaneDir.y > 0.f) {
1186 camAzimuth = -camAzimuth;
1189 camAzimuth = camAzimuth + 0.75f;
1191 const vec4 camYAxis = vec4(normalize(vec3(viewToWorld[1])), 0.5f * viewPortSize.y);
1192 const vec2 waveDirection(cos(windDirection), sin(windDirection));
1193 const vec4 rgba(vec3(oceanData.color), clamp(1.f - oceanData.transparency, 0.f, 1.f));
1195 auto m = oceanMaterial.resolve();
1196 m->setVec4Property(cameraYAxisKey, camYAxis);
1197 m->setVec4Property(waterColorKey, rgba);
1198 m->setVec2Property(waveDirectionKey, vec2(waveDirection));
1199 m->setVec2Property(camPlaneDirKey, camPlaneDir);
1200 m->setFloatProperty(significantWaveHeightKey, significantWaveHeight);
1201 m->setFloatProperty(fftTileScaleKey, 1.f / fftTileExtent);
1202 m->setFloatProperty(camAzimuthKey, camAzimuth);
1203 m->setFloatProperty(seaLevelKey, oceanData.seaLevel);
1204 m->setFloatProperty(reflectionBrightnessKey, oceanData.reflectionBrightness);
1205 m->setFloatProperty(phaseShiftNoiseFrequencyKey,
float(phaseShiftNoiseFrequency));
1206 m->setFloatProperty(phaseShiftNoisePeriodKey,
float(phaseShiftNoiseFrequency*tilePeriod));
1208 m->setVec2Property(m->getVec2Key(
"viewportScale"), 2.f*viewPortSize);
1209 m->setVec2Property(m->getVec2Key(
"valueScale"), 2.f * glm::vec2(magnitudes.channel0, magnitudes.channel1));
1212 for (
auto & tile : gridData.tiles) {
1213 if (oceanData.transparent) {
1214 tile.materialInstance->setTransparent();
1217 tile.materialInstance->setOpaque();
1222void Cogs::Core::BasicOceanSystem::destroyDefaultReflectionCameraIfExists(
Context* context,
BasicOceanData& oceanData)
1224 if (!oceanData.defaultReflectionCamera)
return;
1227 if (
Entity* parent = transform->parent.resolve()->getContainer(); parent) {
1228 context->
store->
removeChild(parent, oceanData.defaultReflectionCamera.get());
1233 oceanData.defaultReflectionCamera.reset();
1234 LOG_DEBUG(logger,
"Destroyed default reflection camera");
1240 destroyDefaultReflectionCameraIfExists(context, oceanData);
1241 base::destroyComponent(component);
1246 if (!pool.size())
return;
1248 updateTextureResolution(&(*pool.begin()));
1250 bool encodingChanged =
false;
1253 bool eightBit = ((context->device->getCapabilities()->getDeviceCapabilities().FloatTextures ==
false) ||
1254 (context->
variables->get(
"basic-ocean.8bit",
true)));
1255 encodingChanged = this->eightBit != eightBit;
1256 this->eightBit = eightBit;
1259 bool visibleInstances =
false;
1263 if (oceanComp.reflectionCamera) {
1264 destroyDefaultReflectionCameraIfExists(context, oceanData);
1265 reflectionCamera = oceanComp.reflectionCamera;
1268 if (!oceanData.defaultReflectionCamera) {
1269 if (
CameraComponent* mainCameraComp = context->cameraSystem->getMainCamera(); mainCameraComp) {
1270 oceanData.defaultReflectionCamera = context->
store->
createChildEntity(
"ReflectionCamera", mainCameraComp->getContainer(),
"BasicOcean Default Reflection Camera");
1271 LOG_DEBUG(logger,
"Created default reflection camera");
1277 reflectionCamera = oceanData.defaultReflectionCamera;
1283 visibleInstances = visibleInstances || sceneComp->visible;
1285 if (!oceanData.initialized) {
1286 context->adaptivePlanarGridSystem->registerMaterial(gridComp, oceanMaterial, initMaterialInstanceCallback, &oceanData);
1287 gridComp->layer = RenderLayers::Ocean;
1288 gridComp->setChanged();
1289 oceanData.initialized =
true;
1292 if (oceanData.reflectionCamera.lock() != reflectionCamera) {
1293 oceanData.reflectionCamera = reflectionCamera;
1295 reflectionComponent->texture = ReflectionTextureH;
1297 LOG_DEBUG(logger,
"Detected new reflection camera, setting up reflection component");
1300 LOG_DEBUG(logger,
"Reflection camera lacks ReflectionComponent");
1304 auto reflectionTex = context->textureManager->get(ReflectionTextureH);
1307 refCamComp->
viewportSize = glm::vec2(reflectionTex->description.width, reflectionTex->description.height);
1310 if (sceneComp->visible) {
1311 switch (oceanComp.reflection) {
1312 case BasicOceanReflection::Planar:
1315 case BasicOceanReflection::EnvSkyBox:
1316 case BasicOceanReflection::EnvRadiance:
1328 if (oceanComp.
hasChanged() || encodingChanged) {
1329 specsChanged =
true;
1331 const char * waveVariant =
nullptr;
1332 switch (oceanComp.waves)
1334 case BasicOceanWaves::Default: waveVariant =
"Basic";
break;
1335 case BasicOceanWaves::Quux: waveVariant =
"Quux";
break;
1336 default: assert(
false);
1339 const char* beliefSystem =
nullptr;
1340 switch (oceanComp.beliefSystem) {
1341 case BasicOceanBeliefSystem::FlatEarth: beliefSystem =
"FlatEarth";
break;
1342 case BasicOceanBeliefSystem::CurvedEarth: beliefSystem =
"CurvedEarth";
break;
1343 default: assert(
false);
1346 const char * reflectionVariant =
nullptr;
1347 switch (oceanComp.reflection) {
1348 case BasicOceanReflection::Planar: reflectionVariant =
"Planar";
break;
1349 case BasicOceanReflection::EnvSkyBox: reflectionVariant =
"EnvSkyBox";
break;
1350 case BasicOceanReflection::EnvRadiance: reflectionVariant =
"EnvRadiance";
break;
1351 default: assert(
false);
1354 const char* lightModelVariant =
nullptr;
1355 lightModelVariant = oceanComp.pbr ?
"PBR" :
"Phong";
1357 const char* encodingVariant = eightBit ?
"Scaled" :
"AsIs";
1359 if ((oceanData.encoding != encodingVariant) ||
1360 (oceanData.waveVariant != waveVariant) ||
1361 (oceanData.reflectionVariant != reflectionVariant) ||
1362 (oceanData.lightModelVariant != lightModelVariant) ||
1363 (oceanData.beliefSystem != beliefSystem))
1365 oceanData.encoding = encodingVariant;
1366 oceanData.waveVariant = waveVariant;
1367 oceanData.beliefSystem = beliefSystem;
1368 oceanData.reflectionVariant = reflectionVariant;
1369 oceanData.lightModelVariant = lightModelVariant;
1371 for (
auto & instance : context->adaptivePlanarGridSystem->getData(gridComp).materialPool) {
1372 instance->setVariant(
"Encoding", encodingVariant);
1373 instance->setVariant(
"Waves", waveVariant);
1374 instance->setVariant(
"BeliefSystem", beliefSystem);
1375 instance->setVariant(
"Reflection", reflectionVariant);
1376 instance->setVariant(
"LightModel", lightModelVariant);
1382 oceanData.color = oceanComp.
color;
1384 oceanData.seaLevel = oceanComp.
seaLevel;
1387 fftTileResolutionLog2 = std::max(1, oceanComp.fftTileResolutionLog2);
1388 significantWaveHeight = oceanComp.significantWaveHeight;
1389 dominantWavePeriod = oceanComp.dominantWavePeriod;
1390 windSpeed = oceanComp.windSpeed;
1391 windDirection = oceanComp.windDirection;
1392 waves = oceanComp.waves;
1394 auto adjustedDisplacement = std::max(significantWaveHeight, 0.01f);
1395 gridComp->displaceMin = glm::vec3(-0.75f * adjustedDisplacement) + glm::vec3(0.f, 0.f, oceanComp.
seaLevel);
1396 gridComp->displaceMax = glm::vec3(0.75f * adjustedDisplacement) + glm::vec3(0.f, 0.f, oceanComp.
seaLevel);
1397 gridComp->setChanged();
1402 setupWaveSpectrum();
1404 for (
auto & oceanComp : pool) {
1407 auto c = glm::cos(windDirection);
1408 auto s = glm::sin(windDirection);
1410 context->adaptivePlanarGridSystem->setTexCoordTransform(gridComp, glm::mat2(c, s, -s, c), glm::vec2(fftTileExtent*tilePeriod));
1414 if (!visibleInstances)
return;
1418 bool doAnimate = context->
variables->get(
"basic-ocean.animate",
true);
1419 if (!doAnimate && !specsChanged) {
1421 specsChanged =
true;
1432 context->
engine->setDirty();
1435 const int N = 1 << fftTileResolutionLog2;
1437 const bool workParallel = context->
engine->workParallel();
1439 extraStep = eightBit && ((doAnimate ==
false) && (this->animate || specsChanged));
1442 const float time = doAnimate ?
static_cast<float>(context->
time->getAnimationTime()) : 7.f;
1443 if (animate || specsChanged) {
1444 if (workParallel ||
true) {
1446 const size_t subRange = N / numTasks;
1450 for (
size_t i = 0; i < numTasks; ++i) {
1451 context->
taskManager->enqueueChild(gr, [&, i, time, N, subRange]()
1455 disperseWaves(frqdDzdu, frqdDzdv, frqDx, frqDy, frqDz, frqH0, time, fftTileExtent, N, i * subRange, (i + 1) * subRange);
1459 context->
taskManager->enqueueChild(oceanTaskGroup, [
this, context, gr]()
1463 context->
taskManager->enqueueChild(gr, [&, context]() { fastInverseFourierTransform2D(context, fftScratch1, spcdDzdu, frqdDzdu, 1.f, fftTileResolutionLog2); });
1464 context->
taskManager->enqueueChild(gr, [&, context]() { fastInverseFourierTransform2D(context, fftScratch2, spcdDzdv, frqdDzdv, 1.f, fftTileResolutionLog2); });
1465 context->
taskManager->enqueueChild(gr, [&, context]() { fastInverseFourierTransform2D(context, fftScratch3, spcDx, frqDx, 1.f, fftTileResolutionLog2); });
1466 context->
taskManager->enqueueChild(gr, [&, context]() { fastInverseFourierTransform2D(context, fftScratch4, spcDy, frqDy, 1.f, fftTileResolutionLog2); });
1467 context->
taskManager->enqueueChild(gr, [&, context]() { fastInverseFourierTransform2D(context, fftScratch5, spcDz, frqDz, 1.f, fftTileResolutionLog2); });
1471 updateTextures(magnitudes.channel0, magnitudes.channel1);
1472 if (this->extraStep) {
1473 LOG_DEBUG(logger,
"Extra texture encoder run to get magnitudes right");
1474 updateTextures(magnitudes_tmp.channel0, magnitudes_tmp.channel1);
1480 disperseWaves(frqdDzdu, frqdDzdv, frqDx, frqDy, frqDz, frqH0, time, fftTileExtent, N, 0, N);
1481 fastInverseFourierTransform2D(context, fftScratch, spcdDzdu, frqdDzdu, 1.f, fftTileResolutionLog2);
1482 fastInverseFourierTransform2D(context, fftScratch, spcdDzdv, frqdDzdv, 1.f, fftTileResolutionLog2);
1483 fastInverseFourierTransform2D(context, fftScratch, spcDx, frqDx, 1.f, fftTileResolutionLog2);
1484 fastInverseFourierTransform2D(context, fftScratch, spcDy, frqDy, 1.f, fftTileResolutionLog2);
1485 fastInverseFourierTransform2D(context, fftScratch, spcDz, frqDz, 1.f, fftTileResolutionLog2);
1495 if (!pool.size())
return;
1498 for (
auto & oceanComp : pool) {
1499 auto & oceanData = getData(&oceanComp);
1501 auto & gridData = context->adaptivePlanarGridSystem->getData(gridComp);
1504 if (
auto e = gridComp->lodReference.lock(); e) {
1508 lodRefComp = context->cameraSystem->getMainCamera()->getComponent<
TransformComponent>();
1512 glm::vec2 viewportSize;
1513 for (
auto & weak : gridComp->cameras) {
1514 if (
auto entity = weak.lock(); entity) {
1516 auto & camData = context->cameraSystem->getData(comp);
1517 viewportSize = glm::max(viewportSize, camData.viewportSize);
1523 viewportSize = context->cameraSystem->getMainCameraData().viewportSize;
1526 updateTileMaterialInstances(oceanData,
1529 context->transformSystem->getLocalToWorld(lodRefComp),
1533 if (animate || specsChanged) {
1537 if (!std::isfinite(magnitudes.channel0) || !std::isfinite(magnitudes.channel1) || specsChanged || this->extraStep) {
1538 magnitudes.channel0 = magnitudes_tmp.channel0;
1539 magnitudes.channel1 = magnitudes_tmp.channel1;
1542 magnitudes.channel0 = 0.9f * magnitudes.channel0 + 0.1f * magnitudes_tmp.channel0;
1543 magnitudes.channel1 = 0.9f * magnitudes.channel1 + 0.1f * magnitudes_tmp.channel1;
1547 specsChanged =
false;
void setChanged()
Sets the component to the ComponentFlags::Changed state with carry.
ComponentType * getComponent() const
Container for components, providing composition of dynamic entities.
float reflectionBrightness
Multiplicative factor reflection.
float seaLevel
Vertical displacement of average sea height.
float transparency
Transparency of water.
glm::vec4 color
Color of water. Alpha taken from transparency component.
void initialize(Context *context) override
Initialize the system.
void destroyComponent(ComponentHandle component) override
Destroy the component held by the given handle.
void cleanup(Context *context) override
Provided for custom cleanup logic in derived systems.
CameraFlags flags
Camera behavior flags.
glm::vec2 viewportSize
Size of the viewport covered by this instance, given in pixels.
Context * context
Pointer to the Context instance the system lives in.
void postUpdate()
Perform post update logic in the system.
virtual void initialize(Context *context)
Initialize the system.
void update()
Updates the system state to that of the current frame.
A Context instance contains all the services, systems and runtime components needed to use Cogs.
class EntityStore * store
Entity store.
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
std::unique_ptr< class Variables > variables
Variables service instance.
std::unique_ptr< class Time > time
Time service instance.
std::unique_ptr< class Engine > engine
Engine instance.
void destroyEntity(const EntityId id)
Destroy the entity with the given id.
EntityPtr createChildEntity(const StringView &type, ComponentModel::Entity *parent, const StringView &name=StringView())
Create a new Entity, parenting it to the given parent.
void removeChild(ComponentModel::Entity *parent, const ComponentModel::Entity *entity)
Remove the parent-child relationship between parent and entity.
Wrapper for mapped texture data, ensuring RAII behavior of stream map/unmap operations.
Contains information on how the entity behaves in the scene.
static constexpr TaskQueueId GlobalQueue
Global task queue.
Log implementation class.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
std::function< void()> TaskFunction
Type of task function used by the task manager.
std::shared_ptr< ComponentModel::Entity > EntityPtr
Smart pointer for Entity access.
@ EnableRender
Renderable.
@ None
No primitive culling performed.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
void COGSFOUNDATION_API log(const char *message, const char *source, const Category category, uint32_t errorNumber)
Logs the given message with source and category.
Handle to a Component instance.
ComponentType * resolveComponent() const
Material instances represent a specialized Material combined with state for all its buffers and prope...
void setName(const StringView &name)
Set the user friendly name of the resource.
Task id struct used to identify unique Task instances.
bool isValid() const
Check if the task id is valid.
Runtime control variable.
@ Clamp
Texture coordinates are clamped to the [0, 1] range.
@ RenderTarget
The texture can be used as a render target and drawn into.