// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "Config.h" #include "Engine/Core/Math/Rectangle.h" #include "Engine/Core/Math/Color.h" struct RenderView; struct RenderContext; struct DrawCall; class IMaterial; class RenderTask; class SceneRenderTask; class DirectionalLight; class PointLight; class SpotLight; class SkyLight; class EnvironmentProbe; class Skybox; class Decal; class MaterialBase; class SkinnedMeshDrawData; class Lightmap; class RenderBuffers; class GPUTextureView; class GPUContext; class GPUBuffer; class GPUTexture; /// /// Interface for objects that can render custom sky /// class ISkyRenderer { public: /// /// Returns true if sky is realtime, otherwise it's static. /// virtual bool IsDynamicSky() const = 0; /// /// Apply sky material/shader state to the GPU pipeline with custom parameters set (render to GBuffer). /// /// The context responsible for rendering commands. /// The rendering context. /// The world matrix to use during sky model vertices transformations. virtual void ApplySky(GPUContext* context, RenderContext& renderContext, const Matrix& world) = 0; }; /// /// Volumetric fog feature settings /// struct VolumetricFogOptions { bool Enable; float ScatteringDistribution; Color Albedo; Color Emissive; float ExtinctionScale; float Distance; Float4 FogParameters; bool UseVolumetricFog() const { return Enable && Distance > 0; } }; /// /// Interface for objects that can render custom fog/atmosphere /// class IFogRenderer { public: /// /// Gets the volumetric fog options. /// /// The result. virtual void GetVolumetricFogOptions(VolumetricFogOptions& result) const = 0; /// /// Gets the exponential height fog data. /// /// The rendering view. /// The result. virtual void GetExponentialHeightFogData(const RenderView& view, ExponentialHeightFogData& result) const = 0; /// /// Draw fog using GBuffer inputs /// /// Context responsible for rendering commands /// The rendering context. /// Output buffer virtual void DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureView* output) = 0; }; /// /// Interface for objects that can render custom atmospheric fog /// class IAtmosphericFogRenderer { public: /// /// Draw fog using GBuffer inputs /// /// Context responsible for rendering commands /// The rendering context. /// Output buffer virtual void DrawFog(GPUContext* context, RenderContext& renderContext, GPUTextureView* output) = 0; }; /// /// Renderer draw call used for dynamic batching process. /// struct DrawCall { /// /// The material to use for rendering. /// IMaterial* Material; struct { /// /// The geometry index buffer (cannot be null). /// GPUBuffer* IndexBuffer; /// /// The geometry vertex buffers. /// GPUBuffer* VertexBuffers[3]; /// /// The geometry vertex buffers byte offsets. /// uint32 VertexBuffersOffsets[3]; } Geometry; /// /// The amount of instances of the geometry to draw. Set to 0 if use indirect draw arguments buffer. /// int32 InstanceCount; union { struct { /// /// The location of the first index read by the GPU from the index buffer. /// int32 StartIndex; /// /// The indices count. /// int32 IndicesCount; }; struct { /// /// The indirect draw arguments offset. /// uint32 IndirectArgsOffset; /// /// The indirect draw arguments buffer. /// GPUBuffer* IndirectArgsBuffer; }; } Draw; // Per-material shader data packed into union union { struct { const Lightmap* Lightmap; Rectangle LightmapUVsArea; } Features; struct { const Lightmap* Lightmap; Rectangle LightmapUVsArea; SkinnedMeshDrawData* Skinning; Float3 GeometrySize; // Object geometry size in the world (unscaled). float LODDitherFactor; // The model LOD transition dither progress. Matrix PrevWorld; } Surface; struct { const Lightmap* Lightmap; Rectangle LightmapUVsArea; Float4 HeightmapUVScaleBias; Float4 NeighborLOD; Float2 OffsetUV; float CurrentLOD; float ChunkSizeNextLOD; float TerrainChunkSizeLOD0; const class TerrainPatch* Patch; } Terrain; struct { class ParticleBuffer* Particles; class ParticleEmitterGraphCPUNode* Module; struct { int32 OrderOffset; float UVTilingDistance; float UVScaleX; float UVScaleY; float UVOffsetX; float UVOffsetY; uint32 SegmentCount; } Ribbon; struct { Float3 Position; float Radius; int32 ParticleIndex; } VolumetricFog; } Particle; struct { GPUBuffer* SplineDeformation; Matrix LocalMatrix; // Geometry transformation applied before deformation. Float3 GeometrySize; // Object geometry size in the world (unscaled). float Segment; float ChunksPerSegment; float MeshMinZ; float MeshMaxZ; } Deformable; struct { byte Raw[96]; } Custom; }; /// /// Object world transformation matrix. /// Matrix World; /// /// Object location in the world used for draw calls sorting. /// Float3 ObjectPosition; /// /// Object bounding sphere radius that contains it whole (sphere at ObjectPosition). /// float ObjectRadius; /// /// The world matrix determinant sign (used for geometry that is two sided or has inverse scale - needs to flip normal vectors and change triangles culling). /// float WorldDeterminantSign; /// /// The random per-instance value (normalized to range 0-1). /// float PerInstanceRandom; /// /// The sorting key for the draw call calculate by RenderList. /// uint64 SortKey; /// /// Zero-init. /// FORCE_INLINE DrawCall() { Platform::MemoryClear(this, sizeof(DrawCall)); } }; template<> struct TIsPODType { enum { Value = true }; }; /// /// Data container for meshes and skinned meshes rendering with minimal state caching. /// Used to update previous world transformation matrix for motion vectors pass and handle LOD transitions blending. /// struct GeometryDrawStateData { /// /// The previous frame world transformation matrix for the given geometry instance. /// Matrix PrevWorld = Matrix::Identity; /// /// The previous frame index. In sync with Engine::FrameCount used to detect new frames and rendering gaps to reset state. /// uint64 PrevFrame = 0; /// /// The previous frame model LOD index used. It's locked during LOD transition to cache the transition start LOD. /// char PrevLOD = -1; /// /// The LOD transition timer. Value 255 means the end of the transition (aka no transition), value 0 means transition started. /// Interpolated between 0-255 to smooth transition over several frames and reduce LOD changing artifacts. /// byte LODTransition = 255; }; template<> struct TIsPODType { enum { Value = true }; }; #define GEOMETRY_DRAW_STATE_EVENT_BEGIN(drawState, worldMatrix) \ const auto frame = Engine::FrameCount; \ if (drawState.PrevFrame + 1 < frame && !renderContext.View.IsSingleFrame) \ { \ drawState.PrevWorld = worldMatrix; \ } #define GEOMETRY_DRAW_STATE_EVENT_END(drawState, worldMatrix) \ if (drawState.PrevFrame != frame && !renderContext.View.IsSingleFrame) \ { \ drawState.PrevWorld = worldMatrix; \ drawState.PrevFrame = frame; \ }