39 _fogStartEnd = { 648.f, 1300.f };
40 _noiseTile = { 15.0f, 15.0f };
41 _noiseFactor = { 0.1f, 0.1f };
42 _refractionTint = { 0.f, 0.567f, 0.845f };
43 _waterDistanceFogColour = { 0.9f, 0.9f, 1.f };
44 _dimensions = { 500u, 500u, 500u };
49 WaterPlane::~WaterPlane()
54 void WaterPlane::onEditorChange( std::string_view )
noexcept
57 if ( _fogStartEnd.y <= _fogStartEnd.y )
59 _fogStartEnd.y = _fogStartEnd.x + 0.1f;
63 bool WaterPlane::load( PlatformContext& context )
65 if ( _plane != INVALID_HANDLE<Quad3D> )
74 const auto name = resourceName();
76 ResourceDescriptor<Quad3D> waterPlane(
"waterPlane" );
77 waterPlane.flag(
true );
78 waterPlane.waitForReady(
true );
82 SamplerDescriptor defaultSampler = {};
86 defaultSampler._anisotropyLevel = 4u;
88 std::atomic_uint loadTasks = 0u;
90 ResourceDescriptor<Texture> waterTexture(
"waterTexture_" + name );
91 waterTexture.assetName(
"terrain_water_NM_old.jpg" );
92 waterTexture.assetLocation( Paths::g_imagesLocation );
93 waterTexture.waitForReady(
false );
97 texDescriptor._textureOptions._alphaChannelTransparency =
false;
99 Handle<Texture> waterNM =
CreateResource( waterTexture, loadTasks );
101 ResourceDescriptor<Material> waterMaterial(
"waterMaterial_" + name );
102 Handle<Material> waterMatHandle =
CreateResource( waterMaterial );
103 ResourcePtr<Material> waterMat =
Get(waterMatHandle);
108 waterMat->properties().isStatic(
true );
114 waterMat->computeShaderCBK( []( [[maybe_unused]] Material* material,
const RenderStagePass stagePass )
116 ShaderModuleDescriptor vertModule = {};
118 vertModule._sourceFile =
"water.glsl";
120 ShaderModuleDescriptor fragModule = {};
122 fragModule._sourceFile =
"water.glsl";
125 shaderDescriptor.
_name =
"waterColour";
130 shaderDescriptor._name =
"waterPrePass";
131 shaderDescriptor._globalDefines.emplace_back(
"PRE_PASS" );
132 shaderDescriptor._modules.push_back( vertModule );
133 shaderDescriptor._modules.push_back( fragModule );
137 shaderDescriptor._name =
"waterDepthPass";
138 shaderDescriptor._modules.push_back( vertModule );
143 shaderDescriptor._modules.push_back( vertModule );
144 shaderDescriptor._modules.push_back( fragModule );
147 shaderDescriptor._globalDefines.emplace_back(
"_refractionTint PushData0[0].xyz" );
148 shaderDescriptor._globalDefines.emplace_back(
"_specularShininess PushData0[0].w" );
149 shaderDescriptor._globalDefines.emplace_back(
"_waterDistanceFogColour PushData0[1].xyz" );
150 shaderDescriptor._globalDefines.emplace_back(
"_noiseTile PushData0[2].xy" );
151 shaderDescriptor._globalDefines.emplace_back(
"_noiseFactor PushData0[2].zw)" );
152 shaderDescriptor._globalDefines.emplace_back(
"_fogStartEndDistances PushData0[3].xy" );
154 return shaderDescriptor;
157 waterMat->properties().roughness( 0.01f );
160 setMaterialTpl( waterMatHandle );
162 const F32 halfWidth = _dimensions.width * 0.5f;
163 const F32 halfLength = _dimensions.height * 0.5f;
165 setBounds( BoundingBox( vec3<F32>( -halfWidth, -_dimensions.depth, -halfLength ), vec3<F32>( halfWidth, 0, halfLength ) ) );
170 void WaterPlane::postLoad( SceneGraphNode* sgn )
172 PlatformContext& pContext = sgn->context();
173 registerEditorComponent( pContext );
176 EditorComponentField blurReflectionField = {};
177 blurReflectionField._name =
"Blur reflections";
178 blurReflectionField._data = &_blurReflections;
180 blurReflectionField._readOnly =
false;
183 _editorComponent->registerField(
MOV( blurReflectionField ) );
185 EditorComponentField blurKernelSizeField = {};
186 blurKernelSizeField._name =
"Blur kernel size";
187 blurKernelSizeField._data = &_blurKernelSize;
189 blurKernelSizeField._readOnly =
false;
192 blurKernelSizeField._range = { 2.f, 20.f };
193 blurKernelSizeField._step = 1.f;
195 _editorComponent->registerField(
MOV( blurKernelSizeField ) );
197 EditorComponentField reflPlaneOffsetField = {};
198 reflPlaneOffsetField._name =
"Reflection Plane Offset";
199 reflPlaneOffsetField._data = &_reflPlaneOffset;
200 reflPlaneOffsetField._range = { -5.0f, 5.0f };
202 reflPlaneOffsetField._readOnly =
false;
205 _editorComponent->registerField(
MOV( reflPlaneOffsetField ) );
207 EditorComponentField refrPlaneOffsetField = {};
208 refrPlaneOffsetField._name =
"Refraction Plane Offset";
209 refrPlaneOffsetField._data = &_refrPlaneOffset;
210 refrPlaneOffsetField._range = { -5.0f, 5.0f };
212 refrPlaneOffsetField._readOnly =
false;
215 _editorComponent->registerField(
MOV( refrPlaneOffsetField ) );
217 EditorComponentField fogDistanceField = {};
218 fogDistanceField._name =
"Fog start/end distances";
219 fogDistanceField._data = &_fogStartEnd;
220 fogDistanceField._range = { 0.0f, 4096.0f };
222 fogDistanceField._readOnly =
false;
225 _editorComponent->registerField(
MOV( fogDistanceField ) );
227 EditorComponentField waterFogField = {};
228 waterFogField._name =
"Water fog colour";
229 waterFogField._data = &_waterDistanceFogColour;
231 waterFogField._readOnly =
false;
234 _editorComponent->registerField(
MOV( waterFogField ) );
236 EditorComponentField noiseTileSizeField = {};
237 noiseTileSizeField._name =
"Noise tile factor";
238 noiseTileSizeField._data = &_noiseTile;
239 noiseTileSizeField._range = { 0.0f, 1000.0f };
241 noiseTileSizeField._readOnly =
false;
244 _editorComponent->registerField(
MOV( noiseTileSizeField ) );
246 EditorComponentField noiseFactorField = {};
247 noiseFactorField._name =
"Noise factor";
248 noiseFactorField._data = &_noiseFactor;
249 noiseFactorField._range = { 0.0f, 10.0f };
251 noiseFactorField._readOnly =
false;
254 _editorComponent->registerField(
MOV( noiseFactorField ) );
256 EditorComponentField refractionTintField = {};
257 refractionTintField._name =
"Refraction tint";
258 refractionTintField._data = &_refractionTint;
260 refractionTintField._readOnly =
false;
263 _editorComponent->registerField(
MOV( refractionTintField ) );
265 EditorComponentField specularShininessField = {};
266 specularShininessField._name =
"Specular Shininess";
267 specularShininessField._data = &_specularShininess;
269 specularShininessField._readOnly =
false;
273 _editorComponent->registerField(
MOV( specularShininessField ) );
275 _editorComponent->onChangedCbk( [
this](
const std::string_view field )
noexcept
277 onEditorChange( field );
279 NavigationComponent* nComp = sgn->get<NavigationComponent>();
280 if ( nComp !=
nullptr )
285 RigidBodyComponent* rComp = sgn->get<RigidBodyComponent>();
286 if ( rComp !=
nullptr )
291 const F32 halfWidth = _dimensions.width * 0.5f;
292 const F32 halfLength = _dimensions.height * 0.5f;
294 Get(_plane)->setCorner( Quad3D::CornerLocation::TOP_LEFT, vec3<F32>( -halfWidth, 0, -halfLength ) );
295 Get(_plane)->setCorner( Quad3D::CornerLocation::TOP_RIGHT, vec3<F32>( halfWidth, 0, -halfLength ) );
296 Get(_plane)->setCorner( Quad3D::CornerLocation::BOTTOM_LEFT, vec3<F32>( -halfWidth, 0, halfLength ) );
297 Get(_plane)->setCorner( Quad3D::CornerLocation::BOTTOM_RIGHT, vec3<F32>( halfWidth, 0, halfLength ) );
298 Get(_plane)->setNormal( Quad3D::CornerLocation::CORNER_ALL,
WORLD_Y_AXIS );
299 _boundingBox.set( vec3<F32>( -halfWidth, -_dimensions.depth, -halfLength ), vec3<F32>( halfWidth, 0, halfLength ) );
301 RenderingComponent* renderable = sgn->get<RenderingComponent>();
304 if ( sgn->context().config().rendering.lodThresholds.x < std::max( halfWidth, halfLength ) )
306 renderable->lockLoD( 0u );
309 renderable->setReflectionCallback( [
this]( RenderPassManager* passManager, RenderCbkParams& params, GFX::CommandBuffer& commandsInOut, GFX::MemoryBarrierCommand& memCmdInOut )
311 updateReflection( passManager, params, commandsInOut, memCmdInOut );
314 renderable->setRefractionCallback( [
this]( RenderPassManager* passManager, RenderCbkParams& params, GFX::CommandBuffer& commandsInOut, GFX::MemoryBarrierCommand& memCmdInOut )
316 updateRefraction( passManager, params, commandsInOut, memCmdInOut );
324 bool WaterPlane::postLoad()
329 bool WaterPlane::unload()
335 void WaterPlane::sceneUpdate(
const U64 deltaTimeUS, SceneGraphNode* sgn, SceneState& sceneState )
337 sceneState.waterBodies().emplace_back(WaterBodyData
339 ._positionW = sgn->get<TransformComponent>()->getWorldPosition(),
340 ._extents = {
to_F32( _dimensions.width ),
341 to_F32( _dimensions.depth ),
342 to_F32( _dimensions.height ),
349 void WaterPlane::prepareRender( SceneGraphNode* sgn,
350 RenderingComponent& rComp,
352 GFX::MemoryBarrierCommand& postDrawMemCmd,
353 const RenderStagePass renderStagePass,
354 const CameraSnapshot& cameraSnapshot,
355 const bool refreshData )
357 PushConstantsStruct& fastData = pkg.pushConstantsCmd()._fastData;
358 fastData.data[0]._vec[0].set( refractionTint(), specularShininess() );
359 fastData.data[0]._vec[1].set( waterDistanceFogColour(), 0.f );
360 fastData.data[0]._vec[2].set( noiseTile(), noiseFactor() );
361 fastData.data[0]._vec[3].xy = fogStartEnd();
366 bool WaterPlane::PointUnderwater(
const SceneGraphNode* sgn,
const vec3<F32>& point )
noexcept
368 return sgn->get<BoundsComponent>()->getBoundingBox().containsPoint( point );
373 GenericDrawCommand& cmd = cmdsOut.emplace_back();
376 cmd._cmd.indexCount =
to_U32(
Get(_plane)->geometryBuffer()->getIndexCount() );
377 cmd._sourceBuffer =
Get(_plane)->geometryBuffer()->handle();
383 void WaterPlane::updateRefraction( RenderPassManager* passManager, RenderCbkParams& renderParams, GFX::CommandBuffer& bufferInOut, GFX::MemoryBarrierCommand& memCmdInOut )
const
387 const bool underwater = PointUnderwater( renderParams._sgn, renderParams._camera->snapshot()._eye );
388 Plane<F32> refractionPlane;
389 updatePlaneEquation( renderParams._sgn, refractionPlane, underwater, refrPlaneOffset() );
392 RenderPassParams params = {};
395 params._sourceNode = renderParams._sgn;
398 params._minExtents.set( 1.0f );
400 params._target = renderParams._renderTarget;
401 params._clippingPlanes.set( 0, refractionPlane );
402 params._passName =
"Refraction";
411 passManager->doCustomPass( renderParams._camera, params, bufferInOut, memCmdInOut );
413 const PlatformContext& context = passManager->parent().platformContext();
414 const RenderTarget* rt = context.gfx().renderTargetPool().getRenderTarget( params._target );
416 GFX::ComputeMipMapsCommand computeMipMapsCommand = {};
423 void WaterPlane::updateReflection( RenderPassManager* passManager, RenderCbkParams& renderParams, GFX::CommandBuffer& bufferInOut, GFX::MemoryBarrierCommand& memCmdInOut )
const
427 const bool underwater = PointUnderwater( renderParams._sgn, renderParams._camera->snapshot()._eye );
433 Plane<F32> reflectionPlane;
434 updatePlaneEquation( renderParams._sgn, reflectionPlane, !underwater, reflPlaneOffset() );
437 renderParams._camera->updateLookAt();
438 _reflectionCam->fromCamera( *renderParams._camera );
442 _reflectionCam->setReflection( reflectionPlane );
445 RenderPassParams params = {};
448 params._sourceNode = renderParams._sgn;
451 params._minExtents.set( 1.5f );
453 params._target = renderParams._renderTarget;
454 params._clippingPlanes.set( 0, reflectionPlane );
455 params._passName =
"Reflection";
461 passManager->doCustomPass( _reflectionCam, params, bufferInOut, memCmdInOut );
463 if ( _blurReflections )
465 RenderTarget* reflectTarget = renderParams._context.renderTargetPool().getRenderTarget( renderParams._renderTarget );
466 RenderTargetHandle reflectionTargetHandle{
468 renderParams._renderTarget
472 RenderTargetHandle reflectionBlurBuffer{
477 renderParams._context.blurTarget( reflectionTargetHandle,
478 reflectionBlurBuffer,
479 reflectionTargetHandle,
488 const PlatformContext& context = passManager->parent().platformContext();
489 const RenderTarget* rt = context.gfx().renderTargetPool().getRenderTarget( params._target );
491 GFX::ComputeMipMapsCommand computeMipMapsCommand = {};
497 void WaterPlane::updatePlaneEquation(
const SceneGraphNode* sgn, Plane<F32>& plane,
const bool reflection,
const F32 offset )
const
499 const F32 waterLevel = sgn->get<TransformComponent>()->getWorldPosition().y * (reflection ? -1.f : 1.f);
500 const Quaternion<F32>& orientation = sgn->get<TransformComponent>()->getWorldOrientation();
505 const vec3<U16>& WaterPlane::getDimensions() const noexcept
510 void WaterPlane::saveToXML( boost::property_tree::ptree& pt )
const
512 pt.put(
"dimensions.<xmlattr>.width", _dimensions.width );
513 pt.put(
"dimensions.<xmlattr>.length", _dimensions.height );
514 pt.put(
"dimensions.<xmlattr>.depth", _dimensions.depth );
519 void WaterPlane::loadFromXML(
const boost::property_tree::ptree& pt )
521 _dimensions.width = pt.get<
U16>(
"dimensions.<xmlattr>.width", _dimensions.width );
522 _dimensions.height = pt.get<
U16>(
"dimensions.<xmlattr>.length", _dimensions.height );
523 _dimensions.depth = pt.get<
U16>(
"dimensions.<xmlattr>.depth", _dimensions.depth );
#define WAIT_FOR_CONDITION(...)
static Camera * CreateCamera(const Str< 256 > &cameraName, Mode cameraMode)
static bool DestroyCamera(Camera *&camera)
static constexpr F32 MAX_SHININESS
virtual void saveToXML(boost::property_tree::ptree &pt) const
virtual void sceneUpdate(U64 deltaTimeUS, SceneGraphNode *sgn, SceneState &sceneState)
Called from SceneGraph "sceneUpdate".
virtual void prepareRender(SceneGraphNode *sgn, RenderingComponent &rComp, RenderPackage &pkg, GFX::MemoryBarrierCommand &postDrawMemCmd, RenderStagePass renderStagePass, const CameraSnapshot &cameraSnapshot, bool refreshData)
bool load(PlatformContext &context) override
Loading and unloading interface.
virtual void buildDrawCommands(SceneGraphNode *sgn, GenericDrawCommandContainer &cmdsOut)
virtual void loadFromXML(const boost::property_tree::ptree &pt)
FORCE_INLINE T * EnqueueCommand(CommandBuffer &buffer)
constexpr F32 g_reflectionPlaneCorrectionHeight
Handle console commands that start with a forward slash.
vec2< T > Normalized(vec2< T > vector) noexcept
constexpr SceneNodeType GetSceneNodeType()
static constexpr bool IsDepthPass(const RenderStagePass stagePass) noexcept
constexpr U32 to_U32(const T value)
FORCE_INLINE void DestroyResource(Handle< T > &handle, const bool immediate=false)
static constexpr U32 RT_DEPTH_ATTACHMENT_IDX
void SetDefaultDrawDescriptor(RenderPassParams ¶ms)
@ RES_LOADING
The resource is loading, creating data, parsing scripts, etc.
static const vec3< F32 > WORLD_Y_NEG_AXIS
void toggleOption(GenericDrawCommand &cmd, CmdRenderOptions option) noexcept
constexpr F32 to_F32(const T value)
FORCE_INLINE Handle< T > CreateResource(const ResourceDescriptor< T > &descriptor, bool &wasInCache, std::atomic_uint &taskCounter)
eastl::fixed_vector< GenericDrawCommand, 1, true > GenericDrawCommandContainer
RTClearEntry DEFAULT_CLEAR_ENTRY
PropertyDescriptor< Texture > TextureDescriptor
PropertyDescriptor< ShaderProgram > ShaderProgramDescriptor
FORCE_INLINE T * Get(const Handle< T > handle)
static const vec3< F32 > WORLD_Y_AXIS
constexpr auto to_base(const Type value) -> Type
static RenderTargetID REFLECTION_PLANAR_BLUR
static RenderTargetID OIT_REFLECT
static RenderTargetID HI_Z_REFLECT