Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
Sky.cpp
Go to the documentation of this file.
1
2
3#include "Headers/Sky.h"
4
8#include "Headers/Sun.h"
9
18
21
22#ifdef _MSC_VER
23# pragma warning (push)
24# pragma warning (disable: 4505)
25#endif
26
27#include <TileableVolumeNoise.h>
28#include <CurlNoise/Curl.h>
29
30#ifndef STBI_INCLUDE_STB_IMAGE_WRITE_H
31#define STB_IMAGE_WRITE_IMPLEMENTATION
32#define STB_IMAGE_WRITE_STATIC
33#include <stb_image_write.h>
34#include <stb_image.h>
35#endif //STBI_INCLUDE_STB_IMAGE_WRITE_H
36#ifdef _MSC_VER
37# pragma warning (pop)
38#endif
39
40namespace Divide
41{
42 namespace
43 {
44 constexpr bool g_alwaysGenerateWeatherTextures = false;
46
47 const auto procLocation = []()
48 {
49 return Paths::g_proceduralTexturesLocation / (g_useGroundTruthTextures ? "ground_truth" : "");
50 };
51
52 const string curlTexName{ "curlnoise.bmp" };
53 const string weatherTexName{ "weather.bmp" };
54 const string worlTexName{ "worlnoise.bmp" };
55 const string perlWorlTexName{ "perlworlnoise.tga" };
56
57 void GenerateCurlNoise( const char* fileName, const I32 width, const I32 height )
58 {
59 Byte* data = new Byte[width * height * 4];
60 memset( data, 255, width * height * 4u );
61
62 constexpr F32 frequency[] = { 8.0f, 6.0f, 4.0f };
63
64 for ( I32 i = 0; i < width * height * 4; i += 4 )
65 {
66 const Vectormath::Aos::Vector3 pos
67 {
68 to_F32( (i / 4) % width ) / width,
69 to_F32( ((i / 4) / height) ) / height,
70 height / 10000.f
71 };
72 for ( U8 pass = 0u; pass < 3; ++pass )
73 {
74 CurlNoise::SetCurlSettings( false, frequency[pass], 3, 2.f, 0.5f );
75 const auto res = CurlNoise::ComputeCurlNoBoundaries( pos );
76 const vec3<F32> curl = Normalized( vec3<F32>{res.val[0], res.val[1], res.val[2]} );
77 const F32 cellFBM0 = curl.r * 0.5f + curl.g * 0.35f + curl.b * 0.15f;
78
79 data[i + pass] = to_byte( cellFBM0 * 128.f + 127.f );
80 }
81 }
82
83 stbi_write_bmp( fileName, width, height, 4, data );
84 delete[] data;
85 }
86
87 void GeneratePerlinNoise( const char* fileName, const I32 width, const I32 height )
88 {
89 const auto smoothstep = []( const F32 edge0, const F32 edge1, const F32 x )
90 {
91 const F32 t = std::min( std::max( (x - edge0) / (edge1 - edge0), 0.0f ), 1.0f );
92 return t * t * (3.f - 2.f * t);
93 };
94
95
96 Byte* data = new Byte[width * height * 4];
97 memset( data, 255, width * height * 4u );
98
99 for ( I32 i = 0; i < width * height * 4; i += 4 )
100 {
101 const glm::vec3 pos = glm::vec3( to_F32( (i / 4) % width ) / to_F32( width ),
102 to_F32( (i / 4) / height ) / to_F32( height ),
103 0.051f );
104 const glm::vec3 offset1 = glm::vec3( 0.f, 0.f, 581.163f );
105 const glm::vec3 offset2 = glm::vec3( 0.f, 0.f, 1245.463f );
106 //const glm::vec3 offset3 = glm::vec3(0.f, 0.f, 2245.863f);
107
108 const F32 perlinNoise = Tileable3dNoise::PerlinNoise( pos, 8, 3 );
109 const F32 perlinNoise2 = Tileable3dNoise::PerlinNoise( pos + offset1, 8, 3 );
110 F32 perlinNoise3 = Tileable3dNoise::PerlinNoise( pos + offset2, 2, 3 );
111 //F32 perlinNoise4 = Tileable3dNoise::PerlinNoise(pos + offset3, 4, 3);
112 perlinNoise3 = std::min( 1.f, (smoothstep( 0.45f, 0.8f, perlinNoise3 ) + smoothstep( 0.25f, 0.45f, perlinNoise3 ) * 0.5f) );
113 data[i + 0] = to_byte( perlinNoise * 128.f + 127.f );
114 data[i + 1] = to_byte( smoothstep( 0.5f, 0.7f, perlinNoise2 ) * 255.f );
115 data[i + 2] = to_byte( perlinNoise3 * 255.f );
116 }
117 stbi_write_bmp( fileName, width, height, 4, data );
118 delete[] data;
119 }
120
121 void GenerateWorleyNoise( const char* fileName, const I32 width, const I32 height, const I32 slices )
122 {
123 Byte* worlNoiseArray = new Byte[slices * width * height * 4];
124 memset( worlNoiseArray, 255, slices * width * height * 4u );
125
126 for ( I32 i = 0; i < slices * width * height * 4; i += 4 )
127 {
128 const glm::vec3 pos = glm::vec3( to_F32( (i / 4) % width ) / to_F32( width ),
129 to_F32( ((i / 4) / height) % height ) / to_F32( height ),
130 to_F32( (i / 4) / (slices * slices) ) / to_F32( slices ) );
131 const F32 cell0 = 1.f - Tileable3dNoise::WorleyNoise( pos, 2.f );
132 const F32 cell1 = 1.f - Tileable3dNoise::WorleyNoise( pos, 4.f );
133 const F32 cell2 = 1.f - Tileable3dNoise::WorleyNoise( pos, 8.f );
134 const F32 cell3 = 1.f - Tileable3dNoise::WorleyNoise( pos, 16.f );
135
136 const F32 cellFBM0 = cell0 * 0.5f + cell1 * 0.35f + cell2 * 0.15f;
137 const F32 cellFBM1 = cell1 * 0.5f + cell2 * 0.35f + cell3 * 0.15f;
138 const F32 cellFBM2 = cell2 * 0.75f + cell3 * 0.25f; // cellCount=4 -> worleyNoise4 is just noise due to sampling frequency=texel freque. So only take into account 2 frequenciM
139 worlNoiseArray[i + 0] = to_byte( cellFBM0 * 255 );
140 worlNoiseArray[i + 1] = to_byte( cellFBM1 * 255 );
141 worlNoiseArray[i + 2] = to_byte( cellFBM2 * 255 );
142 }
143 stbi_write_bmp( fileName, width * slices, height, 4, worlNoiseArray );
144 delete[] worlNoiseArray;
145 }
146
147 void GeneratePerlinWorleyNoise( PlatformContext& context, const char* fileName, const I32 width, const I32 height, const I32 slices )
148 {
149 constexpr bool s_parallelBuild = false;
150
151 Byte* perlWorlNoiseArray = new Byte[slices * width * height * 4];
152
153 const auto cbk = [width, height, slices, perlWorlNoiseArray](const U32 i)
154 {
155 const glm::vec3 pos = glm::vec3( to_F32( (i / 4) % width ) / to_F32( width ),
156 to_F32( ((i / 4) / height) % height ) / to_F32( height ),
157 to_F32( (i / 4) / (slices * slices) ) / to_F32( slices ) );
158 // Perlin FBM noise
159 const F32 perlinNoise = Tileable3dNoise::PerlinNoise( pos, 8, 3 );
160
161 const F32 worleyNoise00 = (1.f - Tileable3dNoise::WorleyNoise( pos, 8 ));
162 const F32 worleyNoise01 = (1.f - Tileable3dNoise::WorleyNoise( pos, 32 ));
163 const F32 worleyNoise02 = (1.f - Tileable3dNoise::WorleyNoise( pos, 56 ));
164 //const F32 worleyNoise3 = (1.f - Tileable3dNoise::WorleyNoise(coord, 80));
165 //const F32 worleyNoise4 = (1.f - Tileable3dNoise::WorleyNoise(coord, 104));
166 //const F32 worleyNoise5 = (1.f - Tileable3dNoise::WorleyNoise(coord, 128)); // half the frequency of texel, we should not go further (with cellCount = 32 and texture size = 64)
167 // PerlinWorley noise as described p.101 of GPU Pro 7
168 const F32 worleyFBM = worleyNoise00 * 0.625f + worleyNoise01 * 0.25f + worleyNoise02 * 0.125f;
169 const F32 PerlWorlNoise = MAP( perlinNoise, 0.f, 1.f, worleyFBM, 1.f );
170
171 //F32 worleyNoise0 = (1.f - Tileable3dNoise::WorleyNoise(coord, 4));
172 //F32 worleyNoise1 = (1.f - Tileable3dNoise::WorleyNoise(coord, 8));
173 const F32 worleyNoise12 = (1.f - Tileable3dNoise::WorleyNoise( pos, 16 ));
174 //F32 worleyNoise3 = (1.f - Tileable3dNoise::WorleyNoise(coord, 32));
175 const F32 worleyNoise14 = (1.f - Tileable3dNoise::WorleyNoise( pos, 64 ));
176 // Three frequency of Worley FBM noise
177 const F32 worleyFBM0 = worleyNoise00 * 0.625f + worleyNoise12 * 0.25f + worleyNoise01 * 0.125f;
178 const F32 worleyFBM1 = worleyNoise12 * 0.625f + worleyNoise01 * 0.25f + worleyNoise14 * 0.125f;
179 const F32 worleyFBM2 = worleyNoise01 * 0.750f + worleyNoise14 * 0.25f; // cellCount=4 -> worleyNoise5 is just noise due to sampling frequency=texel frequency. So only take into account 2 frequencies for FBM
180 perlWorlNoiseArray[i + 0] = to_byte( PerlWorlNoise * 255 );
181 perlWorlNoiseArray[i + 1] = to_byte( worleyFBM0 * 255 );
182 perlWorlNoiseArray[i + 2] = to_byte( worleyFBM1 * 255 );
183 perlWorlNoiseArray[i + 3] = to_byte( worleyFBM2 * 255 );
184 };
185
186 if constexpr ( s_parallelBuild )
187 {
188 ParallelForDescriptor descriptor = {};
189 descriptor._iterCount = slices * width * height * 4u;
190 descriptor._partitionSize = slices;
191 Parallel_For( context.taskPool( TaskPoolType::HIGH_PRIORITY ), descriptor, [&]( const Task*, const U32 start, const U32 end ) -> void
192 {
193 for ( U32 i = start; i < end; i += 4 )
194 {
195 cbk(i);
196 }
197 });
198 }
199 else
200 {
201 for ( U32 i = 0; i < to_U32( slices * width * height * 4u ); i += 4 )
202 {
203 cbk(i);
204 }
205 }
206
207 stbi_write_tga( fileName, width * slices, height, 4, perlWorlNoiseArray );
208 delete[] perlWorlNoiseArray;
209 }
210 }
211
212
213void Sky::OnStartup( PlatformContext& context )
214{
215 static bool init = false;
216 if ( init )
217 {
218 return;
219 }
220
221 init = true;
222 //ref: https://github.com/clayjohn/realtime_clouds/blob/master/gen_noise.cpp
223 std::array<Task*, 3> tasks{ nullptr };
224
225 const ResourcePath curlNoise = procLocation() / curlTexName;
226 const ResourcePath weather = procLocation() / weatherTexName;
227 const ResourcePath worlNoise = procLocation() / worlTexName;
228 const ResourcePath perWordNoise = procLocation() / perlWorlTexName;
229
230 if ( g_alwaysGenerateWeatherTextures || !fileExists( curlNoise ) )
231 {
232 Console::printfn( "Generating Curl Noise 128x128 RGB" );
233 tasks[0] = CreateTask( [fileName = curlNoise.string()]( const Task& )
234 {
235 GenerateCurlNoise( fileName.c_str(), 128, 128 );
236 } );
237 Start( *tasks[0], context.taskPool( TaskPoolType::HIGH_PRIORITY ) );
238 Console::printfn( "Done!" );
239 }
240
241 if ( g_alwaysGenerateWeatherTextures || !fileExists( weather ) )
242 {
243 Console::printfn( "Generating Perlin Noise for LUT's" );
244 Console::printfn( "Generating weather Noise 512x512 RGB" );
245 tasks[1] = CreateTask( [fileName = weather.string()]( const Task& )
246 {
247 GeneratePerlinNoise( fileName.c_str(), 512, 512 );
248 } );
249 Start( *tasks[1], context.taskPool( TaskPoolType::HIGH_PRIORITY ) );
250 Console::printfn( "Done!" );
251 }
252
253 if ( g_alwaysGenerateWeatherTextures || !fileExists( worlNoise ) )
254 {
255 //worley and perlin-worley are from github/sebh/TileableVolumeNoise
256 //which is in turn based on noise described in 'real time rendering of volumetric cloudscapes for horizon zero dawn'
257 Console::printfn( "Generating Worley Noise 32x32x32 RGB" );
258 tasks[2] = CreateTask( [fileName = worlNoise.string()]( const Task& )
259 {
260 GenerateWorleyNoise( fileName.c_str(), 32, 32, 32 );
261 } );
262 Start( *tasks[2], context.taskPool( TaskPoolType::HIGH_PRIORITY ) );
263 Console::printfn( "Done!" );
264 }
265
266 if ( g_alwaysGenerateWeatherTextures || !fileExists( perWordNoise ) )
267 {
268 Console::printfn( "Generating Perlin-Worley Noise 128x128x128 RGBA" );
269 GeneratePerlinWorleyNoise( context, perWordNoise.string().c_str(), 128, 128, 128 );
270 Console::printfn( "Done!" );
271 }
272
273 bool keepWaiting = true;
274 while ( keepWaiting )
275 {
276 keepWaiting = false;
277 for ( Task* task : tasks )
278 {
279 if ( task != nullptr && !Finished( *task ) )
280 {
281 keepWaiting = true;
282 break;
283 }
284 }
285 }
286}
287
288Sky::Sky( const ResourceDescriptor<Sky>& descriptor )
289 : SceneNode( descriptor,
290 GetSceneNodeType<Sky>(),
292 , _diameter( descriptor.ID() )
293{
294 nightSkyColour( { 0.05f, 0.06f, 0.1f, 1.f } );
295 moonColour( { 1.0f, 1.f, 0.8f } );
296
297 const time_t t = time( nullptr );
298 _sun.SetLocation( -2.589910f, 51.45414f ); // Bristol :D
299 _sun.SetDate( *localtime( &t ) );
300
301 _renderState.addToDrawExclusionMask( RenderStage::SHADOW );
302}
303
304bool Sky::load( PlatformContext& context )
305{
306 if ( _sky != INVALID_HANDLE<Sphere3D> )
307 {
308 return false;
309 }
310
311 std::atomic_uint loadTasks = 0u;
312 I32 x, y, n;
313 const string perlWolFile = (procLocation() / perlWorlTexName).string();
314 Byte* perlWorlData = (Byte*)stbi_load( perlWolFile.c_str(), &x, &y, &n, STBI_rgb_alpha );
315 ImageTools::ImageData imgDataPerl = {};
316 if ( !imgDataPerl.loadFromMemory( perlWorlData, to_size( x * y * n ), to_U16( y ), to_U16( y ), to_U16( x / y ), to_U8( STBI_rgb_alpha ) ) )
317 {
319 }
320 stbi_image_free( perlWorlData );
321
322 const string worlFile = (procLocation() / worlTexName).string();
323 Byte* worlNoise = (Byte*)stbi_load( worlFile.c_str(), &x, &y, &n, STBI_rgb_alpha );
324 ImageTools::ImageData imgDataWorl = {};
325 if ( !imgDataWorl.loadFromMemory( worlNoise, to_size( x * y * n ), to_U16( y ), to_U16( y ), to_U16( x / y ), to_U8( STBI_rgb_alpha ) ) )
326 {
328 }
329 stbi_image_free( worlNoise );
330
331 _skyboxSampler._wrapU = TextureWrap::CLAMP_TO_EDGE;
332 _skyboxSampler._wrapV = TextureWrap::CLAMP_TO_EDGE;
333 _skyboxSampler._wrapW = TextureWrap::CLAMP_TO_EDGE;
334 _skyboxSampler._minFilter = TextureFilter::LINEAR;
335 _skyboxSampler._magFilter = TextureFilter::LINEAR;
336 _skyboxSampler._mipSampling = TextureMipSampling::NONE;
337 _skyboxSampler._anisotropyLevel = 0u;
338
339 SamplerDescriptor noiseSamplerMipMap {};
340 noiseSamplerMipMap._wrapU = TextureWrap::REPEAT;
341 noiseSamplerMipMap._wrapV = TextureWrap::REPEAT;
342 noiseSamplerMipMap._wrapW = TextureWrap::REPEAT;
343 noiseSamplerMipMap._minFilter = TextureFilter::LINEAR;
344 noiseSamplerMipMap._magFilter = TextureFilter::LINEAR;
345 noiseSamplerMipMap._mipSampling = TextureMipSampling::LINEAR;
346 noiseSamplerMipMap._anisotropyLevel = 8u;
347 {
348 STUBBED("ToDo: Investigate why weather textures don't work well with DDS conversion using NVTT + STB -Ionut");
349 TextureDescriptor textureDescriptor{};
350 textureDescriptor._texType = TextureType::TEXTURE_3D;
351 textureDescriptor._textureOptions._alphaChannelTransparency = false;
352 textureDescriptor._textureOptions._useDDSCache = false;
353 textureDescriptor._mipMappingState = MipMappingState::AUTO;
354
355 ResourceDescriptor<Texture> perlWorlDescriptor( "perlWorl", textureDescriptor );
356 perlWorlDescriptor.waitForReady( true );
357 _perlWorlNoiseTex = CreateResource( perlWorlDescriptor );
358 Get( _perlWorlNoiseTex )->createWithData( imgDataPerl, {});
359
360 ResourceDescriptor<Texture> worlDescriptor( "worlNoise", textureDescriptor );
361 worlDescriptor.waitForReady( true );
362 _worlNoiseTex = CreateResource( worlDescriptor );
363 Get(_worlNoiseTex)->createWithData( imgDataWorl, {});
364
365 textureDescriptor._texType = TextureType::TEXTURE_2D_ARRAY;
366
367 ResourceDescriptor<Texture> weatherDescriptor( "Weather", textureDescriptor );
368 weatherDescriptor.assetName( weatherTexName );
369 weatherDescriptor.assetLocation( procLocation() );
370 weatherDescriptor.waitForReady( false );
371 _weatherTex = CreateResource( weatherDescriptor );
372
373 ResourceDescriptor<Texture> curlDescriptor( "CurlNoise", textureDescriptor );
374 curlDescriptor.assetName( curlTexName );
375 curlDescriptor.assetLocation( procLocation() );
376 curlDescriptor.waitForReady( false );
377 _curlNoiseTex = CreateResource( curlDescriptor );
378 }
379 {
380 ResourceDescriptor<Texture> skyboxTextures( "SkyTextures" );
381 skyboxTextures.assetName(
382 "skyboxDay_FRONT.jpg, skyboxDay_BACK.jpg, skyboxDay_UP.jpg, skyboxDay_DOWN.jpg, skyboxDay_LEFT.jpg, skyboxDay_RIGHT.jpg," //Day
383 "Milkyway_posx.jpg, Milkyway_negx.jpg, Milkyway_posy.jpg, Milkyway_negy.jpg, Milkyway_posz.jpg, Milkyway_negz.jpg" //Night
384 );
385 skyboxTextures.assetLocation( Paths::g_imagesLocation / "SkyBoxes" );
386 skyboxTextures.waitForReady( false );
387
388 TextureDescriptor& skyboxTexture = skyboxTextures._propertyDescriptor;
390 skyboxTexture._packing = GFXImagePacking::NORMALIZED_SRGB;
391 skyboxTexture._textureOptions._alphaChannelTransparency = false;
392
393 _skybox = CreateResource( skyboxTextures, loadTasks );
394 }
395
396 const F32 radius = _diameter * 0.5f;
397
398 ResourceDescriptor<Sphere3D> skybox( "SkyBox" );
399 skybox.flag( true ); // no default material;
400 skybox.ID( 4 ); // resolution
401 skybox.enumValue( Util::FLOAT_TO_UINT( radius ) ); // radius
402 _sky = CreateResource( skybox );
403
404 ResourcePtr<Sphere3D> skyPtr = Get(_sky);
405 skyPtr->renderState().drawState( false );
406
407 WAIT_FOR_CONDITION( loadTasks.load() == 0u );
408
409 ResourceDescriptor<Material> skyMaterial( "skyMaterial_" + resourceName() );
410 Handle<Material> skyMat = CreateResource( skyMaterial );
411 ResourcePtr<Material> skyMatPtr = Get(skyMat);
412
413 skyMatPtr->updatePriorirty( Material::UpdatePriority::High );
414 skyMatPtr->properties().shadingMode( ShadingMode::BLINN_PHONG );
415 skyMatPtr->properties().roughness( 0.01f );
416 skyMatPtr->setPipelineLayout( PrimitiveTopology::TRIANGLE_STRIP, skyPtr->geometryBuffer()->generateAttributeMap() );
417 skyMatPtr->computeRenderStateCBK( []( [[maybe_unused]] Material* material, const RenderStagePass stagePass, RenderStateBlock& blockInOut)
418 {
419 const bool planarReflection = stagePass._stage == RenderStage::REFLECTION && stagePass._variant == static_cast<RenderStagePass::VariantType>(ReflectorType::PLANAR);
420 blockInOut._cullMode = planarReflection ? CullMode::BACK : CullMode::FRONT;
421 blockInOut._zFunc = IsDepthPass( stagePass ) ? ComparisonFunction::LEQUAL : ComparisonFunction::EQUAL;
422 });
423
424 skyMatPtr->computeShaderCBK( []( [[maybe_unused]] Material* material, const RenderStagePass stagePass )
425 {
426 ShaderModuleDescriptor vertModule = {};
427 vertModule._moduleType = ShaderType::VERTEX;
428 vertModule._sourceFile = "sky.glsl";
429
430 ShaderModuleDescriptor fragModule = {};
431 fragModule._moduleType = ShaderType::FRAGMENT;
432 fragModule._sourceFile = "sky.glsl";
433
434 ShaderProgramDescriptor shaderDescriptor = {};
435
436 if ( IsDepthPass( stagePass ) )
437 {
438 vertModule._variant = "NoClouds";
439 vertModule._defines.emplace_back("NO_ATMOSPHERE", true);
440
441 shaderDescriptor._modules.push_back( vertModule );
442
443 if ( stagePass._stage == RenderStage::DISPLAY )
444 {
445 fragModule._defines.emplace_back( "NO_ATMOSPHERE", true );
446 fragModule._variant = "PrePass";
447 shaderDescriptor._modules.push_back( fragModule );
448 shaderDescriptor._name = "sky_PrePass";
449 }
450 else
451 {
452 shaderDescriptor._name = "sky_Depth";
453 }
454 }
455 else
456 {
457 shaderDescriptor._name = "sky_Display";
458 vertModule._variant = "Clouds";
459 fragModule._variant = "Clouds";
460 shaderDescriptor._modules.push_back( vertModule );
461 shaderDescriptor._modules.push_back( fragModule );
462 }
463
464 shaderDescriptor._globalDefines.emplace_back( "SUN_ENERGY 1000.f" );
465 shaderDescriptor._globalDefines.emplace_back( "SUN_SIZE 0.00872663806f" );
466 shaderDescriptor._globalDefines.emplace_back( "RAYLEIGH_SCALE 7994.f" );
467 shaderDescriptor._globalDefines.emplace_back( "MIE_SCALE 1200.f" );
468 shaderDescriptor._globalDefines.emplace_back( "RAYLEIGH_COEFF vec3(5.5f, 13.0f, 22.4f)" );
469 shaderDescriptor._globalDefines.emplace_back( "MIE_COEFF vec3(21.0f)" );
470
471 shaderDescriptor._globalDefines.emplace_back( "SKIP_REFLECT_REFRACT", true);
472 shaderDescriptor._globalDefines.emplace_back( "dvd_NightSkyColour PushData0[0].xyz" );
473 shaderDescriptor._globalDefines.emplace_back( "dvd_RaySteps PushData0[0].w" );
474 shaderDescriptor._globalDefines.emplace_back( "dvd_MoonColour PushData0[1].xyz" );
475 shaderDescriptor._globalDefines.emplace_back( "dvd_MoonScale PushData0[1].w" );
476 shaderDescriptor._globalDefines.emplace_back( "dvd_UseDaySkybox (int(PushData0[2].x) == 1)" );
477 shaderDescriptor._globalDefines.emplace_back( "dvd_UseNightSkybox (int(PushData0[2].y) == 1)" );
478 shaderDescriptor._globalDefines.emplace_back( "dvd_CloudLayerMinMaxHeight PushData0[2].zw" );
479 shaderDescriptor._globalDefines.emplace_back( "dvd_SunDiskSize PushData0[3].x" );
480 shaderDescriptor._globalDefines.emplace_back( "dvd_PlanetRadius PushData0[3].y" );
481 shaderDescriptor._globalDefines.emplace_back( "dvd_CloudDensity PushData0[3].z" );
482 shaderDescriptor._globalDefines.emplace_back( "dvd_CloudCoverage PushData0[3].w" );
483 shaderDescriptor._globalDefines.emplace_back( "dvd_EnableClouds (int(PushData1[0].x) == 1)" );
484 shaderDescriptor._globalDefines.emplace_back( "dvd_Exposure PushData1[0].y" );
485 shaderDescriptor._globalDefines.emplace_back( "dvd_MieEccentricity PushData1[0].z" );
486 shaderDescriptor._globalDefines.emplace_back( "dvd_Turbidity PushData1[0].w" );
487 shaderDescriptor._globalDefines.emplace_back( "dvd_RayleighColour PushData1[1].xyz" );
488 shaderDescriptor._globalDefines.emplace_back( "dvd_Rayleigh PushData1[1].w" );
489 shaderDescriptor._globalDefines.emplace_back( "dvd_MieColour PushData1[2].xyz" );
490 shaderDescriptor._globalDefines.emplace_back( "dvd_Mie PushData1[2].w" );
491 shaderDescriptor._globalDefines.emplace_back( "dvd_GroundColour PushData1[3].xyz" );
492
493 return shaderDescriptor;
494 });
495
496 WaitForReady( Get(_weatherTex) );
497
498 skyMatPtr->setTexture( TextureSlot::UNIT0, _skybox, _skyboxSampler, TextureOperation::NONE );
499 skyMatPtr->setTexture( TextureSlot::HEIGHTMAP, _weatherTex, noiseSamplerMipMap, TextureOperation::NONE );
500 skyMatPtr->setTexture( TextureSlot::UNIT1, _curlNoiseTex, noiseSamplerMipMap, TextureOperation::NONE );
501 skyMatPtr->setTexture( TextureSlot::SPECULAR, _worlNoiseTex, noiseSamplerMipMap, TextureOperation::NONE );
502 skyMatPtr->setTexture( TextureSlot::NORMALMAP, _perlWorlNoiseTex, noiseSamplerMipMap, TextureOperation::NONE );
503
504 setMaterialTpl( skyMat );
505
506 setBounds( BoundingBox( vec3<F32>( -radius ), vec3<F32>( radius ) ) );
507
508 Console::printfn( LOCALE_STR( "CREATE_SKY_RES_OK" ) );
509
510 return SceneNode::load( context );
511}
512
513void Sky::setSkyShaderData( const RenderStagePass renderStagePass, PushConstantsStruct& constantsInOut )
514{
515 U16 targetRayCount = rayCount();
516 if ( targetRayCount > 16u &&
517 renderStagePass._stage != RenderStage::DISPLAY &&
518 renderStagePass._stage != RenderStage::NODE_PREVIEW )
519 {
520 targetRayCount = std::max<U16>(targetRayCount / 4, 4u);
521 }
522
523 constantsInOut.data[0]._vec[0].set( nightSkyColour().rgb, to_F32( targetRayCount ) );
524 constantsInOut.data[0]._vec[1].set( moonColour().rgb, moonScale() );
525 constantsInOut.data[0]._vec[2].set( useDaySkybox() ? 1.f : 0.f, useNightSkybox() ? 1.f : 0.f, _atmosphere._cloudLayerMinMaxHeight.min, _atmosphere._cloudLayerMinMaxHeight.max );
526 constantsInOut.data[0]._vec[3].set( _atmosphere._sunDiskSize, _atmosphere._planetRadius, _atmosphere._cloudDensity, _atmosphere._cloudCoverage );
527 constantsInOut.data[1]._vec[0].set( enableProceduralClouds() ? 1.f : 0.f, exposure(), _atmosphere._mieEccentricity, _atmosphere._turbidity );
528 constantsInOut.data[1]._vec[1].set( _atmosphere._rayleighColour.r, _atmosphere._rayleighColour.g, _atmosphere._rayleighColour.b, _atmosphere._rayleigh );
529 constantsInOut.data[1]._vec[2].set( _atmosphere._mieColour.r, _atmosphere._mieColour.g, _atmosphere._mieColour.b, _atmosphere._mie );
530 constantsInOut.data[1]._vec[3].set( _groundColour.r, _groundColour.g, _groundColour.b, 0.f );
531}
532
533void Sky::postLoad( SceneGraphNode* sgn )
534{
535 DIVIDE_ASSERT( _sky != INVALID_HANDLE<Sphere3D> );
536
537 SceneGraphNodeDescriptor skyNodeDescriptor;
538 skyNodeDescriptor._serialize = false;
539 skyNodeDescriptor._nodeHandle = FromHandle(_sky);
540 skyNodeDescriptor._name = sgn->name() + "_geometry";
541 skyNodeDescriptor._usageContext = NodeUsageContext::NODE_STATIC;
542 skyNodeDescriptor._componentMask = to_base( ComponentType::TRANSFORM ) |
546 sgn->addChildNode( skyNodeDescriptor )->get<BoundsComponent>()->collisionsEnabled(false);
547 sgn->get<BoundsComponent>()->collisionsEnabled( false );
548
549 RenderingComponent* renderable = sgn->get<RenderingComponent>();
550 if ( renderable )
551 {
552 renderable->lockLoD( 0u );
553 renderable->toggleRenderOption( RenderingComponent::RenderOptions::CAST_SHADOWS, false );
554 renderable->occlusionCull(false);
555 }
556
557 _defaultAtmosphere = atmosphere();
558
559 PlatformContext& pContext = sgn->context();
560 registerEditorComponent( pContext );
561 DIVIDE_ASSERT( _editorComponent != nullptr );
562
563 _editorComponent->onChangedCbk( [this]( const std::string_view field )
564 {
565 if ( field == "Reset To Scene Default" )
566 {
567 _atmosphere = defaultAtmosphere();
568 }
569 else if ( field == "Reset To Global Default" )
570 {
571 _atmosphere = initialAtmosphere();
572 }
573 else if ( field == "Enable Procedural Clouds" )
574 {
575 rebuildDrawCommands( true );
576 }
577 else if ( field == "Update Sky Light" )
578 {
580 }
581
582 _atmosphereChanged = true;
583 } );
584
585 {
586 EditorComponentField separatorField = {};
587 separatorField._name = "Sun/Sky";
588 separatorField._type = EditorComponentFieldType::SEPARATOR;
589 _editorComponent->registerField( MOV( separatorField ) );
590
591 EditorComponentField rayCountField = {};
592 rayCountField._name = "Cloud Ray Count";
593 rayCountField._tooltip = "Base number of rays used for cloud marching";
594 rayCountField._data = &_rayCount;
595 rayCountField._type = EditorComponentFieldType::SLIDER_TYPE;
596 rayCountField._resetValue = 128.f;
597 rayCountField._readOnly = false;
598 rayCountField._range = { 32.f, 512.f };
599 rayCountField._basicType = PushConstantType::UINT;
600 rayCountField._basicTypeSize = PushConstantSize::WORD;
601 _editorComponent->registerField( MOV( rayCountField ) );
602
603 EditorComponentField sunIntensityField = {};
604 sunIntensityField._name = "Sun Disk Size";
605 sunIntensityField._tooltip = "(0.01x - 15.0x) - visual size of the sun disc.";
606 sunIntensityField._data = &_atmosphere._sunDiskSize;
607 sunIntensityField._type = EditorComponentFieldType::SLIDER_TYPE;
608 sunIntensityField._resetValue = 1.f;
609 sunIntensityField._readOnly = false;
610 sunIntensityField._range = { 0.01f, 15.0f };
611 sunIntensityField._basicType = PushConstantType::FLOAT;
612 _editorComponent->registerField( MOV( sunIntensityField ) );
613
614 EditorComponentField skyLuminanceField = {};
615 skyLuminanceField._name = "Exposure";
616 skyLuminanceField._tooltip = "(0.01 - 128.f) - Tone mapping luminance value.";
617 skyLuminanceField._data = &_exposure;
618 skyLuminanceField._type = EditorComponentFieldType::SLIDER_TYPE;
619 skyLuminanceField._readOnly = false;
620 skyLuminanceField._range = { 0.01f, 128.f };
621 skyLuminanceField._basicType = PushConstantType::FLOAT;
622 _editorComponent->registerField( MOV( skyLuminanceField ) );
623 }
624 {
625 EditorComponentField separatorField = {};
626 separatorField._name = "Atmosphere";
627 separatorField._type = EditorComponentFieldType::SEPARATOR;
628 _editorComponent->registerField( MOV( separatorField ) );
629
630 EditorComponentField planetRadiusField = {};
631 planetRadiusField._name = "Planet Radius (m)";
632 planetRadiusField._tooltip = "The radius of the Earth (default: 6371e3m, range: [2000e3m...9000e3m])";
633 planetRadiusField._data = &_atmosphere._planetRadius;
634 planetRadiusField._type = EditorComponentFieldType::PUSH_TYPE;
635 planetRadiusField._resetValue = 6'371'000.f;
636 planetRadiusField._readOnly = false;
637 planetRadiusField._range = { 2'000'000.f, 9'000'000.f };
638 planetRadiusField._basicType = PushConstantType::FLOAT;
639 _editorComponent->registerField( MOV( planetRadiusField ) );
640
641 EditorComponentField cloudHeightOffsetField = {};
642 cloudHeightOffsetField._name = "Cloud height range (m)";
643 cloudHeightOffsetField._tooltip = "Cloud layer will be limited to the range [cloudRadius + x, cloudRadius + y].";
644 cloudHeightOffsetField._data = &_atmosphere._cloudLayerMinMaxHeight;
645 cloudHeightOffsetField._type = EditorComponentFieldType::PUSH_TYPE;
646 cloudHeightOffsetField._readOnly = false;
647 cloudHeightOffsetField._range = { 10.f, 50000.f };
648 cloudHeightOffsetField._basicType = PushConstantType::VEC2;
649 _editorComponent->registerField( MOV( cloudHeightOffsetField ) );
650
651 EditorComponentField rayleighColourField = {};
652 rayleighColourField._name = "Rayleigh Colour";
653 rayleighColourField._data = &_atmosphere._rayleighColour;
654 rayleighColourField._type = EditorComponentFieldType::PUSH_TYPE;
655 rayleighColourField._readOnly = false;
656 rayleighColourField._basicType = PushConstantType::FCOLOUR3;
657 _editorComponent->registerField( MOV( rayleighColourField ) );
658
659 EditorComponentField rayleighField = {};
660 rayleighField._name = "Rayleigh Factor";
661 rayleighField._data = &_atmosphere._rayleigh;
662 rayleighField._type = EditorComponentFieldType::SLIDER_TYPE;
663 rayleighField._resetValue = 2.f;
664 rayleighField._readOnly = false;
665 rayleighField._range = { 0.f, 64.0f };
666 rayleighField._basicType = PushConstantType::FLOAT;
667 _editorComponent->registerField( MOV( rayleighField ) );
668
669 EditorComponentField mieColourField = {};
670 mieColourField._name = "Mie Colour";
671 mieColourField._data = &_atmosphere._mieColour;
672 mieColourField._type = EditorComponentFieldType::PUSH_TYPE;
673 mieColourField._readOnly = false;
674 mieColourField._basicType = PushConstantType::FCOLOUR3;
675 _editorComponent->registerField( MOV( mieColourField ) );
676
677 EditorComponentField mieField = {};
678 mieField._name = "Mie Factor";
679 mieField._data = &_atmosphere._mie;
681 mieField._resetValue = 0.005f;
682 mieField._readOnly = false;
683 mieField._range = { 0.f, 64.0f };
684 mieField._basicType = PushConstantType::FLOAT;
685 _editorComponent->registerField( MOV( mieField ) );
686
687 EditorComponentField mieEccentricityField = {};
688 mieEccentricityField._name = "Mie Eccentricity Factor";
689 mieEccentricityField._data = &_atmosphere._mieEccentricity;
690 mieEccentricityField._type = EditorComponentFieldType::SLIDER_TYPE;
691 mieEccentricityField._resetValue = 0.8f;
692 mieEccentricityField._readOnly = false;
693 mieEccentricityField._range = { -1.f, 1.f };
694 mieEccentricityField._basicType = PushConstantType::FLOAT;
695 _editorComponent->registerField( MOV( mieEccentricityField ) );
696
697 EditorComponentField turbidityField = {};
698 turbidityField._name = "Turbidity Factor";
699 turbidityField._data = &_atmosphere._turbidity;
700 turbidityField._type = EditorComponentFieldType::SLIDER_TYPE;
701 turbidityField._resetValue = 10.f;
702 turbidityField._readOnly = false;
703 turbidityField._range = { 0.f, 1000.f };
704 turbidityField._basicType = PushConstantType::FLOAT;
705 _editorComponent->registerField( MOV( turbidityField ) );
706 }
707 {
708 EditorComponentField separatorField = {};
709 separatorField._name = "Weather";
710 separatorField._type = EditorComponentFieldType::SEPARATOR;
711 _editorComponent->registerField( MOV( separatorField ) );
712
713 EditorComponentField cloudCoverageField = {};
714 cloudCoverageField._name = "Cloud Coverage";
715 cloudCoverageField._data = &_atmosphere._cloudCoverage;
716 cloudCoverageField._type = EditorComponentFieldType::SLIDER_TYPE;
717 cloudCoverageField._resetValue = 0.35f;
718 cloudCoverageField._readOnly = false;
719 cloudCoverageField._range = { 0.001f, 1.f };
720 cloudCoverageField._basicType = PushConstantType::FLOAT;
721 _editorComponent->registerField( MOV( cloudCoverageField ) );
722
723 EditorComponentField cloudDensityField = {};
724 cloudDensityField._name = "Cloud Density";
725 cloudDensityField._data = &_atmosphere._cloudDensity;
726 cloudDensityField._type = EditorComponentFieldType::SLIDER_TYPE;
727 cloudDensityField._resetValue = 0.05f;
728 cloudDensityField._readOnly = false;
729 cloudDensityField._range = { 0.001f, 1.f };
730 cloudDensityField._basicType = PushConstantType::FLOAT;
731 _editorComponent->registerField( MOV( cloudDensityField ) );
732 }
733 {
734 EditorComponentField separator3Field = {};
735 separator3Field._name = "Skybox";
736 separator3Field._type = EditorComponentFieldType::SEPARATOR;
737 _editorComponent->registerField( MOV( separator3Field ) );
738
739 EditorComponentField useDaySkyboxField = {};
740 useDaySkyboxField._name = "Use Day Skybox";
741 useDaySkyboxField._data = &_useDaySkybox;
742 useDaySkyboxField._type = EditorComponentFieldType::PUSH_TYPE;
743 useDaySkyboxField._readOnly = false;
744 useDaySkyboxField._basicType = PushConstantType::BOOL;
745 _editorComponent->registerField( MOV( useDaySkyboxField ) );
746
747 EditorComponentField useNightSkyboxField = {};
748 useNightSkyboxField._name = "Use Night Skybox";
749 useNightSkyboxField._data = &_useNightSkybox;
750 useNightSkyboxField._type = EditorComponentFieldType::PUSH_TYPE;
751 useNightSkyboxField._readOnly = false;
752 useNightSkyboxField._basicType = PushConstantType::BOOL;
753 _editorComponent->registerField( MOV( useNightSkyboxField ) );
754
755 EditorComponentField useProceduralCloudsField = {};
756 useProceduralCloudsField._name = "Enable Procedural Clouds";
757 useProceduralCloudsField._data = &_enableProceduralClouds;
758 useProceduralCloudsField._type = EditorComponentFieldType::PUSH_TYPE;
759 useProceduralCloudsField._readOnly = false;
760 useProceduralCloudsField._basicType = PushConstantType::BOOL;
761 _editorComponent->registerField( MOV( useProceduralCloudsField ) );
762
763 EditorComponentField groundColourField = {};
764 groundColourField._name = "Ground Colour";
765 groundColourField._data = &_groundColour;
766 groundColourField._type = EditorComponentFieldType::PUSH_TYPE;
767 groundColourField._readOnly = false;
768 groundColourField._basicType = PushConstantType::FCOLOUR4;
769 _editorComponent->registerField( MOV( groundColourField ) );
770
771 EditorComponentField nightColourField = {};
772 nightColourField._name = "Night Colour";
773 nightColourField._data = &_nightSkyColour;
774 nightColourField._type = EditorComponentFieldType::PUSH_TYPE;
775 nightColourField._readOnly = false;
776 nightColourField._basicType = PushConstantType::FCOLOUR4;
777 _editorComponent->registerField( MOV( nightColourField ) );
778
779 EditorComponentField moonColourField = {};
780 moonColourField._name = "Moon Colour";
781 moonColourField._data = &_moonColour;
782 moonColourField._type = EditorComponentFieldType::PUSH_TYPE;
783 moonColourField._readOnly = false;
784 moonColourField._basicType = PushConstantType::FCOLOUR4;
785 _editorComponent->registerField( MOV( moonColourField ) );
786
787 EditorComponentField moonScaleField = {};
788 moonScaleField._name = "Moon Scale";
789 moonScaleField._data = &_moonScale;
790 moonScaleField._type = EditorComponentFieldType::PUSH_TYPE;
791 moonScaleField._readOnly = false;
792 moonScaleField._range = { 0.001f, 0.99f };
793 moonScaleField._basicType = PushConstantType::FLOAT;
794 _editorComponent->registerField( MOV( moonScaleField ) );
795 }
796 {
797 EditorComponentField separatorField = {};
798 separatorField._name = "Reset";
799 separatorField._type = EditorComponentFieldType::SEPARATOR;
800 _editorComponent->registerField( MOV( separatorField ) );
801
802 EditorComponentField resetSceneField = {};
803 resetSceneField._name = "Reset To Scene Default";
804 resetSceneField._tooltip = "Default = whatever value was set at load time for this scene.";
805 resetSceneField._type = EditorComponentFieldType::BUTTON;
806 _editorComponent->registerField( MOV( resetSceneField ) );
807
808 EditorComponentField resetGlobalField = {};
809 resetGlobalField._name = "Reset To Global Default";
810 resetGlobalField._tooltip = "Default = whatever value was encoded into the engine.";
811 resetGlobalField._type = EditorComponentFieldType::BUTTON;
812 _editorComponent->registerField( MOV( resetGlobalField ) );
813
814 EditorComponentField rebuildSkyLightField = {};
815 rebuildSkyLightField._name = "Update Sky Light";
816 rebuildSkyLightField._tooltip = "Rebuild the sky light data (refresh sky probe)";
817 rebuildSkyLightField._type = EditorComponentFieldType::BUTTON;
818 _editorComponent->registerField( MOV( rebuildSkyLightField ) );
819 }
820
821 SceneNode::postLoad( sgn );
822}
823
824bool Sky::postLoad()
825{
826 return SceneNode::postLoad();
827}
828
829bool Sky::unload()
830{
831 DestroyResource(_sky);
832 return SceneNode::unload();
833}
834
835const SunInfo& Sky::setDateTime( struct tm* dateTime ) noexcept
836{
837 _sun.SetDate( *dateTime );
838 return getCurrentDetails();
839}
840
841const SunInfo& Sky::setGeographicLocation( const SimpleLocation location ) noexcept
842{
843 _sun.SetLocation( location._longitude, location._latitude );
844 return getCurrentDetails();
845}
846
847const SunInfo& Sky::setDateTimeAndLocation( struct tm* dateTime, SimpleLocation location ) noexcept
848{
849 _sun.SetLocation( location._longitude, location._latitude );
850 _sun.SetDate( *dateTime );
851 return getCurrentDetails();
852}
853
854const SunInfo& Sky::getCurrentDetails() const
855{
856 return _sun.GetDetails();
857}
858
859[[nodiscard]] vec3<F32> Sky::getSunPosition( const F32 radius ) const
860{
861 return _sun.GetSunPosition( radius );
862}
863
864[[nodiscard]] vec3<F32> Sky::getSunDirection( const F32 radius) const
865{
866 return Normalized(getSunPosition(radius));
867}
868
869bool Sky::isDay() const
870{
871 return getCurrentDetails().altitude > 0.f;
872}
873
874SimpleTime Sky::GetTimeOfDay() const noexcept
875{
876 return _sun.GetTimeOfDay();
877}
878
879SimpleLocation Sky::GetGeographicLocation() const noexcept
880{
881 return _sun.GetGeographicLocation();
882}
883
884void Sky::setAtmosphere( const Atmosphere& atmosphere )
885{
886 _atmosphere = atmosphere;
887 _atmosphereChanged = true;
888}
889
890Handle<Texture> Sky::activeSkyBox() const noexcept
891{
892 return _skybox;
893}
894
895void Sky::sceneUpdate( const U64 deltaTimeUS, SceneGraphNode* sgn, SceneState& sceneState )
896{
897 if ( _atmosphereChanged )
898 {
899 if ( _atmosphere._cloudLayerMinMaxHeight < 1.f )
900 {
901 _atmosphere._cloudLayerMinMaxHeight = 1.f;
902 }
903 if ( _atmosphere._cloudLayerMinMaxHeight.min > _atmosphere._cloudLayerMinMaxHeight.max )
904 {
905 std::swap( _atmosphere._cloudLayerMinMaxHeight.min, _atmosphere._cloudLayerMinMaxHeight.max );
906 }
907 _atmosphereChanged = false;
908 }
909
910 SceneNode::sceneUpdate( deltaTimeUS, sgn, sceneState );
911}
912
913void Sky::enableProceduralClouds( const bool val )
914{
915 _enableProceduralClouds = val;
916 _atmosphereChanged = true;
917}
918
919void Sky::useDaySkybox( const bool val )
920{
921 _useDaySkybox = val;
922 _atmosphereChanged = true;
923}
924
925void Sky::useNightSkybox( const bool val )
926{
927 _useNightSkybox = val;
928 _atmosphereChanged = true;
929}
930
931void Sky::moonScale( const F32 val )
932{
933 _moonScale = val;
934 _atmosphereChanged = true;
935}
936
937void Sky::rayCount( const U16 val )
938{
939 _rayCount = CLAMPED<U16>(val, 32u, 512u);
940 _atmosphereChanged = true;
941}
942
943void Sky::exposure( const F32 val )
944{
945 _exposure = CLAMPED(val, 0.01f, 128.0f);
946 _atmosphereChanged = true;
947}
948
949void Sky::moonColour( const FColour4 val )
950{
951 _moonColour = val;
952 _atmosphereChanged = true;
953}
954
955void Sky::nightSkyColour( const FColour4 val )
956{
957 _nightSkyColour = val;
958 _atmosphereChanged = true;
959}
960
961
962void Sky::prepareRender( SceneGraphNode* sgn,
963 RenderingComponent& rComp,
964 RenderPackage& pkg,
965 GFX::MemoryBarrierCommand& postDrawMemCmd,
966 const RenderStagePass renderStagePass,
967 const CameraSnapshot& cameraSnapshot,
968 const bool refreshData )
969{
970
971 setSkyShaderData( renderStagePass, pkg.pushConstantsCmd()._fastData );
972 SceneNode::prepareRender( sgn, rComp, pkg, postDrawMemCmd, renderStagePass, cameraSnapshot, refreshData );
973}
974
975void Sky::buildDrawCommands( SceneGraphNode* sgn, GenericDrawCommandContainer& cmdsOut )
976{
977 GenericDrawCommand& cmd = cmdsOut.emplace_back();
979
980 const VertexBuffer_ptr& skyBuffer = Get(_sky)->geometryBuffer();
981 cmd._sourceBuffer = skyBuffer->handle();
982 cmd._cmd.indexCount = to_U32( skyBuffer->getIndexCount() );
983
985 _atmosphereChanged = true;
986
987 SceneNode::buildDrawCommands( sgn, cmdsOut );
988}
989
990}
#define WAIT_FOR_CONDITION(...)
#define LOCALE_STR(X)
Definition: Localization.h:91
#define MOV(...)
#define DIVIDE_ASSERT(...)
#define STUBBED(x)
#define DIVIDE_UNEXPECTED_CALL()
TaskPool & taskPool(const TaskPoolType type) noexcept
bool unload() override
Definition: SceneNode.cpp:108
virtual void sceneUpdate(U64 deltaTimeUS, SceneGraphNode *sgn, SceneState &sceneState)
Called from SceneGraph "sceneUpdate".
Definition: SceneNode.cpp:44
virtual void prepareRender(SceneGraphNode *sgn, RenderingComponent &rComp, RenderPackage &pkg, GFX::MemoryBarrierCommand &postDrawMemCmd, RenderStagePass renderStagePass, const CameraSnapshot &cameraSnapshot, bool refreshData)
Definition: SceneNode.cpp:50
bool load(PlatformContext &context) override
Loading and unloading interface.
Definition: SceneNode.cpp:98
virtual void buildDrawCommands(SceneGraphNode *sgn, GenericDrawCommandContainer &cmdsOut)
Definition: SceneNode.cpp:115
bool postLoad() override
Definition: SceneNode.cpp:103
U32 FLOAT_TO_UINT(F32 src)
Definition: MathHelper.cpp:345
void GeneratePerlinWorleyNoise(PlatformContext &context, const char *fileName, const I32 width, const I32 height, const I32 slices)
Definition: Sky.cpp:147
void GeneratePerlinNoise(const char *fileName, const I32 width, const I32 height)
Definition: Sky.cpp:87
void GenerateCurlNoise(const char *fileName, const I32 width, const I32 height)
Definition: Sky.cpp:57
constexpr bool g_alwaysGenerateWeatherTextures
Definition: Sky.cpp:44
void GenerateWorleyNoise(const char *fileName, const I32 width, const I32 height, const I32 slices)
Definition: Sky.cpp:121
constexpr bool g_useGroundTruthTextures
Definition: Sky.cpp:45
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
vec2< T > Normalized(vec2< T > vector) noexcept
Definition: MathVectors.inl:98
constexpr SceneNodeType GetSceneNodeType()
Definition: SceneNodeFwd.h:111
static constexpr bool IsDepthPass(const RenderStagePass stagePass) noexcept
std::byte Byte
constexpr U32 to_U32(const T value)
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
vec4< F32 > FColour4
Definition: MathHelper.h:73
constexpr U16 to_U16(const T value)
int32_t I32
uint8_t U8
Task * CreateTask(Predicate &&threadedFunction, bool allowedInIdle=true)
Definition: TaskPool.inl:45
void toggleOption(GenericDrawCommand &cmd, CmdRenderOptions option) noexcept
constexpr F32 to_F32(const T value)
bool Finished(const Task &task) noexcept
Definition: Task.inl:38
@ EQUAL
Passes if the incoming YYY value is equal to the stored YYY value.
void WaitForReady(Resource *res)
Definition: Resource.cpp:27
uint16_t U16
constexpr Byte to_byte(const T value)
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
::value constexpr T MAP(T input, T in_min, T in_max, T out_min, T out_max, D64 &slopeOut) noexcept
Definition: MathHelper.inl:141
constexpr U8 to_U8(const T value)
::value constexpr T CLAMPED(T n, T min, T max) noexcept
Definition: MathHelper.inl:126
eastl::fixed_vector< GenericDrawCommand, 1, true > GenericDrawCommandContainer
void Start(Task &task, TaskPool &pool, TaskPriority priority=TaskPriority::DONT_CARE, const DELEGATE< void > &onCompletionFunction={})
Definition: Task.cpp:9
SceneNodeHandle FromHandle(const Handle< T > handle)
constexpr size_t to_size(const T value)
PropertyDescriptor< Texture > TextureDescriptor
void Parallel_For(TaskPool &pool, const ParallelForDescriptor &descriptor, const DELEGATE< void, const Task *, U32, U32 > &cbk)
Definition: TaskPool.cpp:428
bool fileExists(const ResourcePath &filePathAndName)
PropertyDescriptor< ShaderProgram > ShaderProgramDescriptor
@ BACK
Cull Back facing polygons (aka CW)
@ FRONT
Cull Front facing polygons (aka CCW)
FORCE_INLINE T * Get(const Handle< T > handle)
uint32_t U32
uint64_t U64
constexpr auto to_base(const Type value) -> Type
static NO_INLINE void printfn(const char *format, T &&... args)
U32 _partitionSize
How many elements should we process per async task.
Definition: TaskPool.h:45
U32 _iterCount
For loop iteration count.
Definition: TaskPool.h:43
vector< ShaderModuleDescriptor > _modules