Refactor engine to support double-precision vectors

This commit is contained in:
Wojtek Figat
2022-06-13 00:40:32 +02:00
parent f82e370392
commit a881c90b2e
744 changed files with 19062 additions and 12467 deletions

View File

@@ -341,11 +341,11 @@ void AmbientOcclusionPass::UpdateCB(const RenderContext& renderContext, GPUConte
GBufferPass::SetInputs(view, _constantsBufferData.GBuffer);
Matrix::Transpose(view.View, _constantsBufferData.ViewMatrix);
_constantsBufferData.ViewportPixelSize = Vector2(1.0f / m_sizeX, 1.0f / m_sizeY);
_constantsBufferData.HalfViewportPixelSize = Vector2(1.0f / m_halfSizeX, 1.0f / m_halfSizeY);
_constantsBufferData.ViewportPixelSize = Float2(1.0f / m_sizeX, 1.0f / m_sizeY);
_constantsBufferData.HalfViewportPixelSize = Float2(1.0f / m_halfSizeX, 1.0f / m_halfSizeY);
_constantsBufferData.Viewport2xPixelSize = Vector2(_constantsBufferData.ViewportPixelSize.X * 2.0f, _constantsBufferData.ViewportPixelSize.Y * 2.0f);
_constantsBufferData.Viewport2xPixelSize_x_025 = Vector2(_constantsBufferData.Viewport2xPixelSize.X * 0.25f, _constantsBufferData.Viewport2xPixelSize.Y * 0.25f);
_constantsBufferData.Viewport2xPixelSize = Float2(_constantsBufferData.ViewportPixelSize.X * 2.0f, _constantsBufferData.ViewportPixelSize.Y * 2.0f);
_constantsBufferData.Viewport2xPixelSize_x_025 = Float2(_constantsBufferData.Viewport2xPixelSize.X * 0.25f, _constantsBufferData.Viewport2xPixelSize.Y * 0.25f);
const float tanHalfFOVY = 1.0f / proj.Values[1][1];
@@ -403,7 +403,7 @@ void AmbientOcclusionPass::UpdateCB(const RenderContext& renderContext, GPUConte
const float sa = Math::Sin(angle0);
const float scale = 1.0f + (a - 1.5f + (b - (subPassCount - 1.0f) * 0.5f) / static_cast<float>(subPassCount)) * 0.07f;
_constantsBufferData.PatternRotScaleMatrices[subPass] = Vector4(scale * ca, scale * -sa, -scale * sa, -scale * ca);
_constantsBufferData.PatternRotScaleMatrices[subPass] = Float4(scale * ca, scale * -sa, -scale * sa, -scale * ca);
}
// Update buffer

View File

@@ -22,16 +22,16 @@ private:
PACK_STRUCT(struct ASSAOConstants {
GBufferData GBuffer;
Vector2 ViewportPixelSize;
Vector2 HalfViewportPixelSize;
Float2 ViewportPixelSize;
Float2 HalfViewportPixelSize;
int32 PerPassFullResCoordOffsetX;
int32 PerPassFullResCoordOffsetY;
int32 PassIndex;
float EffectMaxDistance;
Vector2 Viewport2xPixelSize;
Vector2 Viewport2xPixelSize_x_025;
Float2 Viewport2xPixelSize;
Float2 Viewport2xPixelSize_x_025;
float EffectRadius;
float EffectShadowStrength;
@@ -48,7 +48,7 @@ private:
float InvSharpness;
float DetailAOStrength;
Vector4 PatternRotScaleMatrices[5];
Float4 PatternRotScaleMatrices[5];
Matrix ViewMatrix;
});

View File

@@ -14,7 +14,7 @@ private:
PACK_STRUCT(struct Data
{
Vector4 ScreenSize;
Float4 ScreenSize;
});
AssetReference<Shader> _shader;

View File

@@ -17,7 +17,7 @@ private:
PACK_STRUCT(struct Data
{
Vector4 RtSize;
Float4 RtSize;
});
AssetReference<Shader> _shader;

View File

@@ -3,7 +3,6 @@
#include "TAA.h"
#include "Engine/Content/Assets/Shader.h"
#include "Engine/Content/Content.h"
#include "Engine/Core/Config/GraphicsSettings.h"
#include "Engine/Graphics/GPUContext.h"
#include "Engine/Graphics/RenderTargetPool.h"
#include "Engine/Graphics/RenderBuffers.h"
@@ -13,8 +12,8 @@
PACK_STRUCT(struct Data
{
Vector2 ScreenSizeInv;
Vector2 JitterInv;
Float2 ScreenSizeInv;
Float2 JitterInv;
float Sharpness;
float StationaryBlending;
float MotionBlending;

View File

@@ -67,7 +67,7 @@ PACK_STRUCT(struct Data
float AtmosphereR;
int AtmosphereLayer;
float Dummy0;
Vector4 dhdh;
Float4 dhdh;
});
namespace AtmospherePreComputeImpl
@@ -367,7 +367,7 @@ void AtmospherePreComputeService::Dispose()
release();
}
void GetLayerValue(int32 layer, float& atmosphereR, Vector4& dhdh)
void GetLayerValue(int32 layer, float& atmosphereR, Float4& dhdh)
{
float r = layer / Math::Max<float>(InscatterAltitudeSampleNum - 1.0f, 1.0f);
r = r * r;
@@ -377,7 +377,7 @@ void GetLayerValue(int32 layer, float& atmosphereR, Vector4& dhdh)
const float dMinP = r - RadiusGround;
const float dMaxP = Math::Sqrt(r * r - RadiusGround * RadiusGround);
atmosphereR = r;
dhdh = Vector4(dMin, dMax, dMinP, dMaxP);
dhdh = Float4(dMin, dMax, dMinP, dMaxP);
}
void AtmospherePreComputeImpl::onRender(RenderTask* task, GPUContext* context)
@@ -597,7 +597,7 @@ bool DownloadJob::Run()
{
for (int x = 0; x < TransmittanceTexWidth; x++)
{
Vector4 t = ((Half4*)&in->Data[y * in->RowPitch + x * sizeof(Half4)])->ToVector4();
Float4 t = ((Half4*)&in->Data[y * in->RowPitch + x * sizeof(Half4)])->ToFloat4();
*p++ = Math::Saturate(t.Z) * 255;
*p++ = Math::Saturate(t.Y) * 255;
*p++ = Math::Saturate(t.X) * 255;
@@ -630,7 +630,7 @@ bool DownloadJob::Run()
{
for (int x = 0; x < IrradianceTexWidth; x++)
{
Vector4 t = ((Half4*)&in->Data[y * in->RowPitch + x * sizeof(Half4)])->ToVector4();
Float4 t = ((Half4*)&in->Data[y * in->RowPitch + x * sizeof(Half4)])->ToFloat4();
*p++ = Math::Saturate(t.Z) * 255;
*p++ = Math::Saturate(t.Y) * 255;
*p++ = Math::Saturate(t.X) * 255;
@@ -667,7 +667,7 @@ bool DownloadJob::Run()
{
for (int x = 0; x < InscatterWidth; x++)
{
Vector4 t = ((Half4*)&s[y * in->RowPitch + x * sizeof(Half4)])->ToVector4();
Float4 t = ((Half4*)&s[y * in->RowPitch + x * sizeof(Half4)])->ToFloat4();
*p++ = Math::Saturate(t.Z) * 255;
*p++ = Math::Saturate(t.Y) * 255;
*p++ = Math::Saturate(t.X) * 255;

View File

@@ -9,30 +9,30 @@
#include "Engine/Graphics/RenderTask.h"
PACK_STRUCT(struct Data {
Vector4 ColorSaturationShadows;
Vector4 ColorContrastShadows;
Vector4 ColorGammaShadows;
Vector4 ColorGainShadows;
Vector4 ColorOffsetShadows;
Float4 ColorSaturationShadows;
Float4 ColorContrastShadows;
Float4 ColorGammaShadows;
Float4 ColorGainShadows;
Float4 ColorOffsetShadows;
Vector4 ColorSaturationMidtones;
Vector4 ColorContrastMidtones;
Vector4 ColorGammaMidtones;
Vector4 ColorGainMidtones;
Vector4 ColorOffsetMidtones;
Float4 ColorSaturationMidtones;
Float4 ColorContrastMidtones;
Float4 ColorGammaMidtones;
Float4 ColorGainMidtones;
Float4 ColorOffsetMidtones;
Vector4 ColorSaturationHighlights;
Vector4 ColorContrastHighlights;
Vector4 ColorGammaHighlights;
Vector4 ColorGainHighlights;
Vector4 ColorOffsetHighlights;
Float4 ColorSaturationHighlights;
Float4 ColorContrastHighlights;
Float4 ColorGammaHighlights;
Float4 ColorGainHighlights;
Float4 ColorOffsetHighlights;
float ColorCorrectionShadowsMax;
float ColorCorrectionHighlightsMin;
float WhiteTemp;
float WhiteTint;
Vector3 Dummy;
Float3 Dummy;
float LutWeight;
});

View File

@@ -12,9 +12,9 @@
/// </summary>
struct GBufferData
{
Vector4 ViewInfo;
Vector4 ScreenSize;
Vector3 ViewPos;
Float4 ViewInfo;
Float4 ScreenSize;
Float3 ViewPos;
float ViewFar;
Matrix InvViewMatrix;
Matrix InvProjectionMatrix;
@@ -25,7 +25,7 @@ struct GBufferData
/// </summary>
struct ExponentialHeightFogData
{
Vector3 FogInscatteringColor;
Float3 FogInscatteringColor;
float FogMinOpacity;
float FogDensity;
@@ -33,10 +33,10 @@ struct ExponentialHeightFogData
float FogHeightFalloff;
float FogAtViewPosition;
Vector3 InscatteringLightDirection;
Float3 InscatteringLightDirection;
float ApplyDirectionalInscattering;
Vector3 DirectionalInscatteringColor;
Float3 DirectionalInscatteringColor;
float DirectionalInscatteringExponent;
float FogCutoffDistance;
@@ -60,10 +60,10 @@ struct AtmosphericFogData
float AtmosphericFogPower;
float AtmosphericFogDistanceOffset;
Vector3 AtmosphericFogSunDirection;
Float3 AtmosphericFogSunDirection;
float AtmosphericFogSunPower;
Vector3 AtmosphericFogSunColor;
Float3 AtmosphericFogSunColor;
float AtmosphericFogDensityOffset;
};
@@ -71,14 +71,14 @@ struct AtmosphericFogData
/// Structure that contains information about light for shaders.
/// </summary>
PACK_STRUCT(struct LightData {
Vector2 SpotAngles;
Float2 SpotAngles;
float SourceRadius;
float SourceLength;
Vector3 Color;
Float3 Color;
float MinRoughness;
Vector3 Position;
Float3 Position;
float CastShadows;
Vector3 Direction;
Float3 Direction;
float Radius;
float FalloffExponent;
float InverseSquared;
@@ -90,14 +90,14 @@ PACK_STRUCT(struct LightData {
/// Structure that contains information about light for shaders.
/// </summary>
PACK_STRUCT(struct LightShadowData {
Vector2 ShadowMapSize;
Float2 ShadowMapSize;
float Sharpness;
float Fade;
float NormalOffsetScale;
float Bias;
float FadeDistance;
uint32 NumCascades;
Vector4 CascadeSplits;
Float4 CascadeSplits;
Matrix ShadowVP[6];
});
@@ -105,8 +105,8 @@ PACK_STRUCT(struct LightShadowData {
/// Packed env probe data
/// </summary>
PACK_STRUCT(struct ProbeData {
Vector4 Data0; // x - Position.x, y - Position.y, z - Position.z, w - unused
Vector4 Data1; // x - Radius , y - 1 / Radius, z - Brightness, w - unused
Float4 Data0; // x - Position.x, y - Position.y, z - Position.z, w - unused
Float4 Data1; // x - Radius , y - 1 / Radius, z - Brightness, w - unused
});
// Minimum roughness value used for shading (prevent 0 roughness which causes NaNs in Vis_SmithJointApprox)

View File

@@ -16,34 +16,34 @@ class DepthOfFieldPass : public RendererPass<DepthOfFieldPass>
private:
PACK_STRUCT(struct Data {
Vector2 ProjectionAB;
Float2 ProjectionAB;
float BokehDepthCullThreshold;
float BokehDepthCutoff;
Vector4 DOFDepths;
Float4 DOFDepths;
float MaxBokehSize;
float BokehBrightnessThreshold;
float BokehBlurThreshold;
float BokehFalloff;
Vector2 BokehTargetSize;
Vector2 DOFTargetSize;
Float2 BokehTargetSize;
Float2 DOFTargetSize;
Vector2 InputSize;
Float2 InputSize;
float DepthLimit;
float BlurStrength;
Vector3 Dummy;
Float3 Dummy;
float BokehBrightness;
});
// Structure used for outputting bokeh points to an AppendStructuredBuffer
struct BokehPoint
{
Vector3 Position;
Float3 Position;
float Blur;
Vector3 Color;
Float3 Color;
};
bool _platformSupportsDoF = false;

View File

@@ -55,7 +55,7 @@ struct VolumetricFogOptions
Color Emissive;
float ExtinctionScale;
float Distance;
Vector4 FogParameters;
Float4 FogParameters;
bool UseVolumetricFog() const
{
@@ -184,7 +184,7 @@ struct DrawCall
const Lightmap* Lightmap;
Rectangle LightmapUVsArea;
SkinnedMeshDrawData* Skinning;
Vector3 GeometrySize; // Object geometry size in the world (unscaled).
Float3 GeometrySize; // Object geometry size in the world (unscaled).
float LODDitherFactor; // The model LOD transition dither progress.
Matrix PrevWorld;
} Surface;
@@ -193,9 +193,9 @@ struct DrawCall
{
const Lightmap* Lightmap;
Rectangle LightmapUVsArea;
Vector4 HeightmapUVScaleBias;
Vector4 NeighborLOD;
Vector2 OffsetUV;
Float4 HeightmapUVScaleBias;
Float4 NeighborLOD;
Float2 OffsetUV;
float CurrentLOD;
float ChunkSizeNextLOD;
float TerrainChunkSizeLOD0;
@@ -221,7 +221,7 @@ struct DrawCall
struct
{
Vector3 Position;
Float3 Position;
float Radius;
int32 ParticleIndex;
} VolumetricFog;
@@ -231,7 +231,7 @@ struct DrawCall
{
GPUBuffer* SplineDeformation;
Matrix LocalMatrix; // Geometry transformation applied before deformation.
Vector3 GeometrySize; // Object geometry size in the world (unscaled).
Float3 GeometrySize; // Object geometry size in the world (unscaled).
float Segment;
float ChunksPerSegment;
float MeshMinZ;
@@ -252,7 +252,7 @@ struct DrawCall
/// <summary>
/// Object location in the world used for draw calls sorting.
/// </summary>
Vector3 ObjectPosition;
Float3 ObjectPosition;
/// <summary>
/// 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).

View File

@@ -21,9 +21,9 @@ PACK_STRUCT(struct LightmapUVsDensityMaterialShaderData {
Matrix ViewProjectionMatrix;
Matrix WorldMatrix;
Rectangle LightmapArea;
Vector3 WorldInvScale;
Float3 WorldInvScale;
float LightmapTexelsPerWorldUnit;
Vector3 Dummy0;
Float3 Dummy0;
float LightmapSize;
});
@@ -176,10 +176,10 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params)
LightmapUVsDensityMaterialShaderData data;
Matrix::Transpose(params.RenderContext.View.Frustum.GetMatrix(), data.ViewProjectionMatrix);
Matrix::Transpose(drawCall.World, data.WorldMatrix);
const float scaleX = Vector3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
const float scaleY = Vector3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length();
const float scaleZ = Vector3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length();
data.WorldInvScale = Vector3(
const float scaleX = Float3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length();
const float scaleY = Float3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length();
const float scaleZ = Float3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length();
data.WorldInvScale = Float3(
scaleX > 0.00001f ? 1.0f / scaleX : 0.0f,
scaleY > 0.00001f ? 1.0f / scaleY : 0.0f,
scaleZ > 0.00001f ? 1.0f / scaleZ : 0.0f);
@@ -203,14 +203,14 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params)
}
}
BoundingBox box = drawCallModelLod->GetBox(drawCall.World);
Vector3 size = box.GetSize();
Float3 size = box.GetSize();
float dimensionsCoeff = size.AverageArithmetic();
if (size.X <= 1.0f)
dimensionsCoeff = Vector2(size.Y, size.Z).AverageArithmetic();
dimensionsCoeff = Float2(size.Y, size.Z).AverageArithmetic();
else if (size.Y <= 1.0f)
dimensionsCoeff = Vector2(size.X, size.Z).AverageArithmetic();
dimensionsCoeff = Float2(size.X, size.Z).AverageArithmetic();
else if (size.Z <= 1.0f)
dimensionsCoeff = Vector2(size.Y, size.X).AverageArithmetic();
dimensionsCoeff = Float2(size.Y, size.X).AverageArithmetic();
float scale = globalObjectsScale * scaleInLightmap * ShadowsOfMordor::LightmapTexelsPerWorldUnit * dimensionsCoeff;
if (scale <= ZeroTolerance)
scale = 0.0f;

View File

@@ -75,8 +75,8 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context,
// Draw sky
auto box = skyModel->GetBox();
Matrix m1, m2;
Matrix::Scaling(renderContext.View.Far / (box.GetSize().Y * 0.5f) * 0.95f, m1);
Matrix::CreateWorld(renderContext.View.Position, Vector3::Up, Vector3::Backward, m2);
Matrix::Scaling(renderContext.View.Far / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1);
Matrix::CreateWorld(renderContext.View.Position, Float3::Up, Float3::Backward, m2);
m1 *= m2;
drawCall.World = m1;
drawCall.ObjectPosition = drawCall.World.GetTranslation();

View File

@@ -3,7 +3,7 @@
#include "EyeAdaptationPass.h"
#include "HistogramPass.h"
#include "RenderList.h"
#include "Engine/Core/Math/Int2.h"
#include "Engine/Core/Math/Vector2.h"
#include "Engine/Content/Assets/Shader.h"
#include "Engine/Content/Content.h"
#include "Engine/Graphics/GPUDevice.h"

View File

@@ -21,7 +21,7 @@
PACK_STRUCT(struct GBufferPassData{
GBufferData GBuffer;
Vector3 Dummy0;
Float3 Dummy0;
int32 ViewMode;
});
@@ -229,8 +229,8 @@ void GBufferPass::Fill(RenderContext& renderContext, GPUTextureView* lightBuffer
// Calculate sphere model transform to cover far plane
Matrix m1, m2;
Matrix::Scaling(view.Far / (box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum
Matrix::CreateWorld(view.Position, Vector3::Up, Vector3::Backward, m2); // Rotate sphere model
Matrix::Scaling(view.Far / ((float)box.GetSize().Y * 0.5f) * 0.95f, m1); // Scale to fit whole view frustum
Matrix::CreateWorld(view.Position, Float3::Up, Float3::Backward, m2); // Rotate sphere model
m1 *= m2;
// Draw sky

View File

@@ -34,13 +34,13 @@
PACK_STRUCT(struct Data0
{
Vector3 ViewWorldPos;
Float3 ViewWorldPos;
float ViewNearPlane;
float Padding00;
uint32 CulledObjectsCapacity;
float LightShadowsStrength;
float ViewFarPlane;
Vector4 ViewFrustumWorldRays[4];
Float4 ViewFrustumWorldRays[4];
GlobalSignDistanceFieldPass::ConstantsData GlobalSDF;
GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas;
LightData Light;
@@ -55,9 +55,9 @@ PACK_STRUCT(struct AtlasTileVertex
struct GlobalSurfaceAtlasTile : RectPack<GlobalSurfaceAtlasTile, uint16>
{
Vector3 ViewDirection;
Vector3 ViewPosition;
Vector3 ViewBoundsSize;
Float3 ViewDirection;
Float3 ViewPosition;
Float3 ViewBoundsSize;
Matrix ViewMatrix;
uint32 Address;
uint32 ObjectAddressOffset;
@@ -133,7 +133,7 @@ public:
// Cached data to be reused during RasterizeActor
uint64 CurrentFrame;
float ResolutionInv;
Vector3 ViewPosition;
Float3 ViewPosition;
float TileTexelsPerWorldUnit;
float DistanceScalingStart;
float DistanceScalingEnd;
@@ -354,10 +354,10 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
_objectsBuffer = New<DynamicTypedBuffer>(256 * (GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE + GLOBAL_SURFACE_ATLAS_TILE_DATA_STRIDE * 3 / 4), PixelFormat::R32G32B32A32_Float, false, TEXT("GlobalSurfaceAtlas.ObjectsBuffer"));
// Utility for writing into tiles vertex buffer
const Vector2 posToClipMul(2.0f * resolutionInv, -2.0f * resolutionInv);
const Vector2 posToClipAdd(-1.0f, 1.0f);
const Float2 posToClipMul(2.0f * resolutionInv, -2.0f * resolutionInv);
const Float2 posToClipAdd(-1.0f, 1.0f);
#define VB_WRITE_TILE_POS_ONLY(tile) \
Vector2 minPos((float)tile->X, (float)tile->Y), maxPos((float)(tile->X + tile->Width), (float)(tile->Y + tile->Height)); \
Float2 minPos((float)tile->X, (float)tile->Y), maxPos((float)(tile->X + tile->Width), (float)(tile->Y + tile->Height)); \
Half2 min(minPos * posToClipMul + posToClipAdd), max(maxPos * posToClipMul + posToClipAdd); \
auto* quad = _vertexBuffer->WriteReserve<AtlasTileVertex>(6); \
quad[0].Position = max; \
@@ -367,9 +367,9 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
quad[4].Position = { max.X, min.Y }; \
quad[5].Position = quad[0].Position
#define VB_WRITE_TILE(tile) \
Vector2 minPos((float)tile->X, (float)tile->Y), maxPos((float)(tile->X + tile->Width), (float)(tile->Y + tile->Height)); \
Float2 minPos((float)tile->X, (float)tile->Y), maxPos((float)(tile->X + tile->Width), (float)(tile->Y + tile->Height)); \
Half2 min(minPos * posToClipMul + posToClipAdd), max(maxPos * posToClipMul + posToClipAdd); \
Vector2 minUV(0, 0), maxUV(1, 1); \
Float2 minUV(0, 0), maxUV(1, 1); \
auto* quad = _vertexBuffer->WriteReserve<AtlasTileVertex>(6); \
quad[0] = { { max }, { maxUV }, tile->Address }; \
quad[1] = { { min.X, max.Y }, { minUV.X, maxUV.Y }, tile->Address }; \
@@ -399,7 +399,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
surfaceAtlasData.DistanceScaling = 0.1f; // The scale for tiles at distanceScalingEnd and further away
// TODO: add DetailsScale param to adjust quality of scene details in Global Surface Atlas
const uint32 viewMask = renderContext.View.RenderLayersMask;
const Vector3 viewPosition = renderContext.View.Position;
const Float3 viewPosition = renderContext.View.Position;
const float minObjectRadius = 20.0f; // Skip too small objects
for (auto* scene : renderContext.List->Scenes)
{
@@ -585,7 +585,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
uint32 counter = data[surfaceAtlasData.CulledObjectsCounterIndex];
_culledObjectsSizeBuffer->Unmap();
if (counter > 0)
objectsBufferCapacity = counter * sizeof(Vector4);
objectsBufferCapacity = counter * sizeof(Float4);
}
}
if (surfaceAtlasData.CulledObjectsCounterIndex == -1)
@@ -614,7 +614,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
surfaceAtlasData.CulledObjectsBuffer = GPUDevice::Instance->CreateBuffer(TEXT("GlobalSurfaceAtlas.CulledObjectsBuffer"));
if (surfaceAtlasData.CulledObjectsBuffer->GetSize() < objectsBufferCapacity)
{
const GPUBufferDescription desc = GPUBufferDescription::Buffer(objectsBufferCapacity, GPUBufferFlags::UnorderedAccess | GPUBufferFlags::ShaderResource, PixelFormat::R32G32B32A32_Float, nullptr, sizeof(Vector4));
const GPUBufferDescription desc = GPUBufferDescription::Buffer(objectsBufferCapacity, GPUBufferFlags::UnorderedAccess | GPUBufferFlags::ShaderResource, PixelFormat::R32G32B32A32_Float, nullptr, sizeof(Float4));
if (surfaceAtlasData.CulledObjectsBuffer->Init(desc))
return true;
}
@@ -648,11 +648,11 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
{
for (int32 x = 0; x < GLOBAL_SURFACE_ATLAS_CHUNKS_RESOLUTION; x++)
{
Vector3 chunkCoord(x, y, z);
Vector3 chunkMin = result.GlobalSurfaceAtlas.ViewPos + (chunkCoord - (GLOBAL_SURFACE_ATLAS_CHUNKS_RESOLUTION * 0.5f)) * result.GlobalSurfaceAtlas.ChunkSize;
Vector3 chunkMax = chunkMin + result.GlobalSurfaceAtlas.ChunkSize;
Float3 chunkCoord(x, y, z);
Float3 chunkMin = result.GlobalSurfaceAtlas.ViewPos + (chunkCoord - (GLOBAL_SURFACE_ATLAS_CHUNKS_RESOLUTION * 0.5f)) * result.GlobalSurfaceAtlas.ChunkSize;
Float3 chunkMax = chunkMin + result.GlobalSurfaceAtlas.ChunkSize;
BoundingBox chunkBounds(chunkMin, chunkMax);
if (Vector3::Distance(chunkBounds.GetCenter(), result.GlobalSurfaceAtlas.ViewPos) >= 2000.0f)
if (Float3::Distance(chunkBounds.GetCenter(), result.GlobalSurfaceAtlas.ViewPos) >= 2000.0f)
continue;
int32 count = 0;
@@ -725,7 +725,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
{
auto* tile = object.Tiles[tileIndex];
if (!tile || Vector3::Dot(tile->ViewDirection, light.Direction) < ZeroTolerance)
if (!tile || Float3::Dot(tile->ViewDirection, light.Direction) < ZeroTolerance)
continue;
VB_WRITE_TILE(tile);
}
@@ -747,7 +747,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
for (const auto& e : surfaceAtlasData.Objects)
{
const auto& object = e.Value;
Vector3 lightToObject = object.Bounds.GetCenter() - light.Position;
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
continue;
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
@@ -774,13 +774,13 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
for (const auto& e : surfaceAtlasData.Objects)
{
const auto& object = e.Value;
Vector3 lightToObject = object.Bounds.GetCenter() - light.Position;
Float3 lightToObject = object.Bounds.GetCenter() - light.Position;
if (lightToObject.LengthSquared() >= Math::Square(object.Radius + light.Radius))
continue;
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
{
auto* tile = object.Tiles[tileIndex];
if (!tile || Vector3::Dot(tile->ViewDirection, light.Direction) < ZeroTolerance)
if (!tile || Float3::Dot(tile->ViewDirection, light.Direction) < ZeroTolerance)
continue;
VB_WRITE_TILE(tile);
}
@@ -817,14 +817,14 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
}
PROFILE_GPU_CPU("Global Surface Atlas Debug");
const Vector2 outputSize(output->Size());
const Float2 outputSize(output->Size());
{
Data0 data;
data.ViewWorldPos = renderContext.View.Position;
data.ViewNearPlane = renderContext.View.Near;
data.ViewFarPlane = renderContext.View.Far;
for (int32 i = 0; i < 4; i++)
data.ViewFrustumWorldRays[i] = Vector4(renderContext.List->FrustumCornersWs[i + 4], 0);
data.ViewFrustumWorldRays[i] = Float4(renderContext.List->FrustumCornersWs[i + 4], 0);
data.GlobalSDF = bindingDataSDF.Constants;
data.GlobalSurfaceAtlas = bindingData.Constants;
context->UpdateCB(_cb0, &data);
@@ -841,8 +841,8 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
context->SetState(_psDebug);
context->SetRenderTarget(output->View());
{
Vector2 outputSizeThird = outputSize * 0.333f;
Vector2 outputSizeTwoThird = outputSize * 0.666f;
Float2 outputSizeThird = outputSize * 0.333f;
Float2 outputSizeTwoThird = outputSize * 0.666f;
// Full screen - direct light
context->BindSR(11, bindingData.AtlasLighting->View());
@@ -870,8 +870,8 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex
void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, const BoundingSphere& actorObjectBounds, const Matrix& localToWorld, const BoundingBox& localBounds, uint32 tilesMask)
{
GlobalSurfaceAtlasCustomBuffer& surfaceAtlasData = *_surfaceAtlasData;
Vector3 boundsSize = localBounds.GetSize() * actor->GetScale();
const float distanceScale = Math::Lerp(1.0f, surfaceAtlasData.DistanceScaling, Math::InverseLerp(surfaceAtlasData.DistanceScalingStart, surfaceAtlasData.DistanceScalingEnd, CollisionsHelper::DistanceSpherePoint(actorObjectBounds, surfaceAtlasData.ViewPosition)));
Float3 boundsSize = localBounds.GetSize() * actor->GetScale();
const float distanceScale = Math::Lerp(1.0f, surfaceAtlasData.DistanceScaling, Math::InverseLerp(surfaceAtlasData.DistanceScalingStart, surfaceAtlasData.DistanceScalingEnd, (float)CollisionsHelper::DistanceSpherePoint(actorObjectBounds, surfaceAtlasData.ViewPosition)));
const float tilesScale = surfaceAtlasData.TileTexelsPerWorldUnit * distanceScale;
GlobalSurfaceAtlasObject* object = surfaceAtlasData.Objects.TryGet(actorObject);
bool anyTile = false, dirty = false;
@@ -881,7 +881,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
continue;
// Calculate optimal tile resolution for the object side
Vector3 boundsSizeTile = boundsSize;
Float3 boundsSizeTile = boundsSize;
boundsSizeTile.Raw[tileIndex / 2] = MAX_float; // Ignore depth size
uint16 tileResolution = (uint16)(boundsSizeTile.GetAbsolute().MinValue() * tilesScale);
if (tileResolution < 4)
@@ -945,7 +945,7 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
object->LastFrameUsed = surfaceAtlasData.CurrentFrame;
object->Bounds = OrientedBoundingBox(localBounds);
object->Bounds.Transform(localToWorld);
object->Radius = actorObjectBounds.Radius;
object->Radius = (float)actorObjectBounds.Radius;
if (dirty || GLOBAL_SURFACE_ATLAS_DEBUG_FORCE_REDRAW_TILES)
{
object->LastFrameDirty = surfaceAtlasData.CurrentFrame;
@@ -955,16 +955,16 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
// Write to objects buffer (this must match unpacking logic in HLSL)
Matrix worldToLocalBounds;
Matrix::Invert(object->Bounds.Transformation, worldToLocalBounds);
uint32 objectAddress = _objectsBuffer->Data.Count() / sizeof(Vector4);
auto* objectData = _objectsBuffer->WriteReserve<Vector4>(GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE);
objectData[0] = *(Vector4*)&actorObjectBounds;
objectData[1] = Vector4::Zero; // w unused
objectData[2] = Vector4(worldToLocalBounds.M11, worldToLocalBounds.M12, worldToLocalBounds.M13, worldToLocalBounds.M41);
objectData[3] = Vector4(worldToLocalBounds.M21, worldToLocalBounds.M22, worldToLocalBounds.M23, worldToLocalBounds.M42);
objectData[4] = Vector4(worldToLocalBounds.M31, worldToLocalBounds.M32, worldToLocalBounds.M33, worldToLocalBounds.M43);
objectData[5] = Vector4(object->Bounds.Extents, 0.0f); // w unused
uint32 objectAddress = _objectsBuffer->Data.Count() / sizeof(Float4);
auto* objectData = _objectsBuffer->WriteReserve<Float4>(GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE);
objectData[0] = *(Float4*)&actorObjectBounds;
objectData[1] = Float4::Zero; // w unused
objectData[2] = Float4(worldToLocalBounds.M11, worldToLocalBounds.M12, worldToLocalBounds.M13, worldToLocalBounds.M41);
objectData[3] = Float4(worldToLocalBounds.M21, worldToLocalBounds.M22, worldToLocalBounds.M23, worldToLocalBounds.M42);
objectData[4] = Float4(worldToLocalBounds.M31, worldToLocalBounds.M32, worldToLocalBounds.M33, worldToLocalBounds.M43);
objectData[5] = Float4(object->Bounds.Extents, 0.0f); // w unused
auto tileOffsets = reinterpret_cast<uint16*>(&objectData[1]); // xyz used for tile offsets packed into uint16
auto objectDataSize = reinterpret_cast<uint32*>(&objectData[1].W); // w used for object size (count of Vector4s for object+tiles)
auto objectDataSize = reinterpret_cast<uint32*>(&objectData[1].W); // w used for object size (count of Float4s for object+tiles)
*objectDataSize = GLOBAL_SURFACE_ATLAS_OBJECT_DATA_STRIDE;
for (int32 tileIndex = 0; tileIndex < 6; tileIndex++)
{
@@ -977,41 +977,41 @@ void GlobalSurfaceAtlasPass::RasterizeActor(Actor* actor, void* actorObject, con
*objectDataSize += GLOBAL_SURFACE_ATLAS_TILE_DATA_STRIDE;
// Setup view to render object from the side
Vector3 xAxis, yAxis, zAxis = Vector3::Zero;
Float3 xAxis, yAxis, zAxis = Float3::Zero;
zAxis.Raw[tileIndex / 2] = tileIndex & 1 ? 1.0f : -1.0f;
yAxis = tileIndex == 2 || tileIndex == 3 ? Vector3::Right : Vector3::Up;
Vector3::Cross(yAxis, zAxis, xAxis);
Vector3 localSpaceOffset = -zAxis * object->Bounds.Extents;
Vector3::TransformNormal(xAxis, object->Bounds.Transformation, xAxis);
Vector3::TransformNormal(yAxis, object->Bounds.Transformation, yAxis);
Vector3::TransformNormal(zAxis, object->Bounds.Transformation, zAxis);
yAxis = tileIndex == 2 || tileIndex == 3 ? Float3::Right : Float3::Up;
Float3::Cross(yAxis, zAxis, xAxis);
Float3 localSpaceOffset = -zAxis * object->Bounds.Extents;
Float3::TransformNormal(xAxis, object->Bounds.Transformation, xAxis);
Float3::TransformNormal(yAxis, object->Bounds.Transformation, yAxis);
Float3::TransformNormal(zAxis, object->Bounds.Transformation, zAxis);
xAxis.NormalizeFast();
yAxis.NormalizeFast();
zAxis.NormalizeFast();
Vector3::Transform(localSpaceOffset, object->Bounds.Transformation, tile->ViewPosition);
Float3::Transform(localSpaceOffset, object->Bounds.Transformation, tile->ViewPosition);
tile->ViewDirection = zAxis;
// Create view matrix
tile->ViewMatrix.SetColumn1(Vector4(xAxis, -Vector3::Dot(xAxis, tile->ViewPosition)));
tile->ViewMatrix.SetColumn2(Vector4(yAxis, -Vector3::Dot(yAxis, tile->ViewPosition)));
tile->ViewMatrix.SetColumn3(Vector4(zAxis, -Vector3::Dot(zAxis, tile->ViewPosition)));
tile->ViewMatrix.SetColumn4(Vector4(0, 0, 0, 1));
tile->ViewMatrix.SetColumn1(Float4(xAxis, -Float3::Dot(xAxis, tile->ViewPosition)));
tile->ViewMatrix.SetColumn2(Float4(yAxis, -Float3::Dot(yAxis, tile->ViewPosition)));
tile->ViewMatrix.SetColumn3(Float4(zAxis, -Float3::Dot(zAxis, tile->ViewPosition)));
tile->ViewMatrix.SetColumn4(Float4(0, 0, 0, 1));
// Calculate object bounds size in the view
OrientedBoundingBox viewBounds(object->Bounds);
viewBounds.Transform(tile->ViewMatrix);
Vector3 viewExtent;
Vector3::TransformNormal(viewBounds.Extents, viewBounds.Transformation, viewExtent);
Float3 viewExtent;
Float3::TransformNormal(viewBounds.Extents, viewBounds.Transformation, viewExtent);
tile->ViewBoundsSize = viewExtent.GetAbsolute() * 2.0f;
// Per-tile data
const float tileWidth = (float)tile->Width - GLOBAL_SURFACE_ATLAS_TILE_PADDING;
const float tileHeight = (float)tile->Height - GLOBAL_SURFACE_ATLAS_TILE_PADDING;
auto* tileData = _objectsBuffer->WriteReserve<Vector4>(GLOBAL_SURFACE_ATLAS_TILE_DATA_STRIDE);
tileData[0] = Vector4(tile->X, tile->Y, tileWidth, tileHeight) * surfaceAtlasData.ResolutionInv;
tileData[1] = Vector4(tile->ViewMatrix.M11, tile->ViewMatrix.M12, tile->ViewMatrix.M13, tile->ViewMatrix.M41);
tileData[2] = Vector4(tile->ViewMatrix.M21, tile->ViewMatrix.M22, tile->ViewMatrix.M23, tile->ViewMatrix.M42);
tileData[3] = Vector4(tile->ViewMatrix.M31, tile->ViewMatrix.M32, tile->ViewMatrix.M33, tile->ViewMatrix.M43);
tileData[4] = Vector4(tile->ViewBoundsSize, 0.0f); // w unused
auto* tileData = _objectsBuffer->WriteReserve<Float4>(GLOBAL_SURFACE_ATLAS_TILE_DATA_STRIDE);
tileData[0] = Float4(tile->X, tile->Y, tileWidth, tileHeight) * surfaceAtlasData.ResolutionInv;
tileData[1] = Float4(tile->ViewMatrix.M11, tile->ViewMatrix.M12, tile->ViewMatrix.M13, tile->ViewMatrix.M41);
tileData[2] = Float4(tile->ViewMatrix.M21, tile->ViewMatrix.M22, tile->ViewMatrix.M23, tile->ViewMatrix.M42);
tileData[3] = Float4(tile->ViewMatrix.M31, tile->ViewMatrix.M32, tile->ViewMatrix.M33, tile->ViewMatrix.M43);
tileData[4] = Float4(tile->ViewBoundsSize, 0.0f); // w unused
}
}

View File

@@ -13,7 +13,7 @@ public:
// Constant buffer data for Global Surface Atlas access on a GPU.
PACK_STRUCT(struct ConstantsData
{
Vector3 ViewPos;
Float3 ViewPos;
float Padding0;
float Padding1;
float Resolution;

View File

@@ -2,7 +2,7 @@
#include "GlobalSignDistanceFieldPass.h"
#include "RenderList.h"
#include "Engine/Core/Math/Int3.h"
#include "Engine/Core/Math/Vector3.h"
#include "Engine/Core/Collections/HashSet.h"
#include "Engine/Engine/Engine.h"
#include "Engine/Content/Content.h"
@@ -37,21 +37,21 @@ PACK_STRUCT(struct ObjectRasterizeData
{
Matrix WorldToVolume; // TODO: use 3x4 matrix
Matrix VolumeToWorld; // TODO: use 3x4 matrix
Vector3 VolumeToUVWMul;
Float3 VolumeToUVWMul;
float MipOffset;
Vector3 VolumeToUVWAdd;
Float3 VolumeToUVWAdd;
float DecodeMul;
Vector3 VolumeLocalBoundsExtent;
Float3 VolumeLocalBoundsExtent;
float DecodeAdd;
});
PACK_STRUCT(struct Data
{
Vector3 ViewWorldPos;
Float3 ViewWorldPos;
float ViewNearPlane;
Vector3 Padding00;
Float3 Padding00;
float ViewFarPlane;
Vector4 ViewFrustumWorldRays[4];
Float4 ViewFrustumWorldRays[4];
GlobalSignDistanceFieldPass::ConstantsData GlobalSDF;
});
@@ -59,9 +59,9 @@ PACK_STRUCT(struct ModelsRasterizeData
{
Int3 ChunkCoord;
float MaxDistance;
Vector3 CascadeCoordToPosMul;
Float3 CascadeCoordToPosMul;
int ObjectsCount;
Vector3 CascadeCoordToPosAdd;
Float3 CascadeCoordToPosAdd;
int32 CascadeResolution;
float Padding0;
float CascadeVoxelSize;
@@ -74,9 +74,9 @@ struct RasterizeModel
{
Matrix WorldToVolume;
Matrix VolumeToWorld;
Vector3 VolumeToUVWMul;
Vector3 VolumeToUVWAdd;
Vector3 VolumeLocalBoundsExtent;
Float4 VolumeToUVWMul;
Float4 VolumeToUVWAdd;
Float4 VolumeLocalBoundsExtent;
float MipOffset;
const ModelBase::SDFData* SDF;
};
@@ -430,8 +430,8 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
{
cascade.NonEmptyChunks.Clear();
cascade.StaticChunks.Clear();
context->ClearUA(cascade.Texture, Vector4::One);
context->ClearUA(cascade.Mip, Vector4::One);
context->ClearUA(cascade.Texture, Float4::One);
context->ClearUA(cascade.Mip, Float4::One);
}
LOG(Info, "Global SDF memory usage: {0} MB", (sdfData.Cascades[0].Texture->GetMemoryUsage() + sdfData.Cascades[0].Mip->GetMemoryUsage()) * ARRAY_COUNT(sdfData.Cascades) / 1024 / 1024);
}
@@ -517,8 +517,8 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
return true;
}
ModelsRasterizeData data;
data.CascadeCoordToPosMul = cascadeBounds.GetSize() / resolution;
data.CascadeCoordToPosAdd = cascadeBounds.Minimum + voxelSize * 0.5f;
data.CascadeCoordToPosMul = (Float3)cascadeBounds.GetSize() / (float)resolution;
data.CascadeCoordToPosAdd = (Float3)cascadeBounds.Minimum + voxelSize * 0.5f;
data.MaxDistance = maxDistance;
data.CascadeResolution = resolution;
data.CascadeMipResolution = resolutionMip;
@@ -752,7 +752,7 @@ void GlobalSignDistanceFieldPass::RenderDebug(RenderContext& renderContext, GPUC
}
PROFILE_GPU_CPU("Global SDF Debug");
const Vector2 outputSize(output->Size());
const Float2 outputSize(output->Size());
{
Data data;
data.ViewWorldPos = renderContext.View.Position;
@@ -808,8 +808,8 @@ void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBas
mipLevelIndex--;
// Volume -> Local -> UVW
Vector3 volumeToUVWMul = sdf.LocalToUVWMul;
Vector3 volumeToUVWAdd = sdf.LocalToUVWAdd + (localVolumeBounds.Minimum + volumeLocalBoundsExtent) * sdf.LocalToUVWMul;
Float3 volumeToUVWMul = sdf.LocalToUVWMul;
Float3 volumeToUVWAdd = sdf.LocalToUVWAdd + (localVolumeBounds.Minimum + volumeLocalBoundsExtent) * sdf.LocalToUVWMul;
// Add object data for the GPU buffer
uint16 objectIndex = _objectsBufferCount++;
@@ -862,7 +862,7 @@ void GlobalSignDistanceFieldPass::RasterizeModelSDF(Actor* actor, const ModelBas
}
}
void GlobalSignDistanceFieldPass::RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Matrix& localToWorld, const BoundingBox& objectBounds, const Vector4& localToUV)
void GlobalSignDistanceFieldPass::RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Matrix& localToWorld, const BoundingBox& objectBounds, const Float4& localToUV)
{
if (!heightfield || heightfield->ResidentMipLevels() == 0)
return;
@@ -885,8 +885,8 @@ void GlobalSignDistanceFieldPass::RasterizeHeightfield(Actor* actor, GPUTexture*
Matrix::Invert(localToWorld, worldToLocal);
Matrix::Transpose(worldToLocal, objectData.WorldToVolume);
Matrix::Transpose(localToWorld, objectData.VolumeToWorld);
objectData.VolumeToUVWMul = Vector3(localToUV.X, 1.0f, localToUV.Y);
objectData.VolumeToUVWAdd = Vector3(localToUV.Z, 0.0f, localToUV.W);
objectData.VolumeToUVWMul = Float3(localToUV.X, 1.0f, localToUV.Y);
objectData.VolumeToUVWAdd = Float3(localToUV.Z, 0.0f, localToUV.W);
objectData.MipOffset = (float)_cascadeIndex * 0.5f; // Use lower-quality mip for far cascades
_objectsBuffer->Write(objectData);
_objectsTextures.Add(heightfield->View());

View File

@@ -13,9 +13,9 @@ public:
// Constant buffer data for Global SDF access on a GPU.
PACK_STRUCT(struct ConstantsData
{
Vector4 CascadePosDistance[4];
Vector4 CascadeVoxelSize;
Vector3 Padding;
Float4 CascadePosDistance[4];
Float4 CascadeVoxelSize;
Float3 Padding;
float Resolution;
});
@@ -78,7 +78,7 @@ public:
// Rasterize Model SDF into the Global SDF. Call it from actor Draw() method during DrawPass::GlobalSDF.
void RasterizeModelSDF(Actor* actor, const ModelBase::SDFData& sdf, const Matrix& localToWorld, const BoundingBox& objectBounds);
void RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Matrix& localToWorld, const BoundingBox& objectBounds, const Vector4& localToUV);
void RasterizeHeightfield(Actor* actor, GPUTexture* heightfield, const Matrix& localToWorld, const BoundingBox& objectBounds, const Float4& localToUV);
private:
#if COMPILE_WITH_DEV_ENV

View File

@@ -233,7 +233,7 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
// Cache data
auto& light = mainCache->PointLights[lightIndex];
float lightRadius = light.Radius;
Vector3 lightPosition = light.Position;
Float3 lightPosition = light.Position;
const bool renderShadow = useShadows && CanRenderShadow(view, light) && ShadowsPass::Instance()->CanRenderShadow(renderContext, light);
bool useIES = light.IESTexture != nullptr;
@@ -290,7 +290,7 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
// Cache data
auto& light = mainCache->SpotLights[lightIndex];
float lightRadius = light.Radius;
Vector3 lightPosition = light.Position;
Float3 lightPosition = light.Position;
const bool renderShadow = useShadows && CanRenderShadow(view, light) && ShadowsPass::Instance()->CanRenderShadow(renderContext, light);
bool useIES = light.IESTexture != nullptr;
@@ -384,7 +384,7 @@ void LightPass::RenderLight(RenderContext& renderContext, GPUTextureView* lightB
// Cache data
auto& light = mainCache->SkyLights[lightIndex];
float lightRadius = light.Radius;
Vector3 lightPosition = light.Position;
Float3 lightPosition = light.Position;
// Get distance from view center to light center less radius (check if view is inside a sphere)
float distance = ViewToCenterLessRadius(view, lightPosition, lightRadius * sphereModelScale);

View File

@@ -21,15 +21,15 @@ PACK_STRUCT(struct Data {
GBufferData GBuffer;
Matrix CurrentVP;
Matrix PreviousVP;
Vector4 TemporalAAJitter;
Float4 TemporalAAJitter;
float VelocityScale;
float Dummy0;
int32 MaxBlurSamples;
uint32 VariableTileLoopCount;
Vector2 Input0SizeInv;
Vector2 Input2SizeInv;
Float2 Input0SizeInv;
Float2 Input2SizeInv;
});
MotionBlurPass::MotionBlurPass()
@@ -297,7 +297,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP
data.VelocityScale = settings.Scale * 0.5f * timeScale; // 2x samples in loop
data.MaxBlurSamples = Math::Clamp(settings.SampleCount / 2, 1, 64); // 2x samples in loop
data.VariableTileLoopCount = tileSize / 8;
data.Input0SizeInv = Vector2(1.0f / (float)motionVectorsWidth, 1.0f / (float)motionVectorsWidth);
data.Input0SizeInv = Float2(1.0f / (float)motionVectorsWidth, 1.0f / (float)motionVectorsWidth);
const auto cb = _shader->GetShader()->GetCB(0);
context->UpdateCB(cb, &data);
context->BindCB(0, cb);
@@ -319,7 +319,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP
context->SetRenderTarget(vMaxBuffer4->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, vMaxBuffer2->View());
data.Input0SizeInv = Vector2(1.0f / (float)vMaxBuffer2->Width(), 1.0f / (float)vMaxBuffer2->Height());
data.Input0SizeInv = Float2(1.0f / (float)vMaxBuffer2->Width(), 1.0f / (float)vMaxBuffer2->Height());
context->UpdateCB(cb, &data);
context->SetState(_psTileMax);
context->DrawFullscreenTriangle();
@@ -333,7 +333,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP
context->SetRenderTarget(vMaxBuffer8->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, vMaxBuffer4->View());
data.Input0SizeInv = Vector2(1.0f / (float)vMaxBuffer4->Width(), 1.0f / (float)vMaxBuffer4->Height());
data.Input0SizeInv = Float2(1.0f / (float)vMaxBuffer4->Width(), 1.0f / (float)vMaxBuffer4->Height());
context->UpdateCB(cb, &data);
context->SetState(_psTileMax);
context->DrawFullscreenTriangle();
@@ -347,7 +347,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP
context->SetRenderTarget(vMaxBuffer->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, vMaxBuffer8->View());
data.Input0SizeInv = Vector2(1.0f / (float)vMaxBuffer8->Width(), 1.0f / (float)vMaxBuffer8->Height());
data.Input0SizeInv = Float2(1.0f / (float)vMaxBuffer8->Width(), 1.0f / (float)vMaxBuffer8->Height());
context->UpdateCB(cb, &data);
context->SetState(_psTileMaxVariable);
context->DrawFullscreenTriangle();
@@ -370,8 +370,8 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP
context->BindSR(1, motionVectors->View());
context->BindSR(2, vMaxNeighborBuffer->View());
context->BindSR(3, renderContext.Buffers->DepthBuffer->View());
data.Input0SizeInv = Vector2(1.0f / (float)input->Width(), 1.0f / (float)input->Height());
data.Input2SizeInv = Vector2(1.0f / (float)renderContext.Buffers->DepthBuffer->Width(), 1.0f / (float)renderContext.Buffers->DepthBuffer->Height());
data.Input0SizeInv = Float2(1.0f / (float)input->Width(), 1.0f / (float)input->Height());
data.Input2SizeInv = Float2(1.0f / (float)renderContext.Buffers->DepthBuffer->Width(), 1.0f / (float)renderContext.Buffers->DepthBuffer->Height());
context->UpdateCB(cb, &data);
context->SetState(_psMotionBlur);
context->DrawFullscreenTriangle();

View File

@@ -148,8 +148,8 @@ void PostProcessingPass::GB_ComputeKernel(float sigma, float width, float height
// Calculate total weights sum
total += weight;
GaussianBlurCacheH[index] = Vector4(weight, i * xOffset, 0, 0);
GaussianBlurCacheV[index] = Vector4(weight, i * yOffset, 0, 0);
GaussianBlurCacheH[index] = Float4(weight, i * xOffset, 0, 0);
GaussianBlurCacheV[index] = Float4(weight, i * yOffset, 0, 0);
}
// Normalize weights
@@ -160,7 +160,7 @@ void PostProcessingPass::GB_ComputeKernel(float sigma, float width, float height
}
// Assign size
_gbData.Size = Vector2(width, height);
_gbData.Size = Float2(width, height);
}
void PostProcessingPass::Dispose()
@@ -279,12 +279,12 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
data.LensBias = settings.LensFlares.ThresholdBias;
data.LensScale = settings.LensFlares.ThresholdScale;
data.LensInputDistortion = Vector2(-(1.0f / w4) * settings.LensFlares.Distortion, (1.0f / w4) * settings.LensFlares.Distortion);
data.LensInputDistortion = Float2(-(1.0f / w4) * settings.LensFlares.Distortion, (1.0f / w4) * settings.LensFlares.Distortion);
// Calculate star texture rotation matrix
Vector3 camX = renderContext.View.View.GetRight();
Vector3 camZ = renderContext.View.View.GetForward();
float camRot = Vector3::Dot(camX, Vector3::Forward) + Vector3::Dot(camZ, Vector3::Up);
Float3 camX = renderContext.View.View.GetRight();
Float3 camZ = renderContext.View.View.GetForward();
float camRot = Float3::Dot(camX, Float3::Forward) + Float3::Dot(camZ, Float3::Up);
float camRotCos = Math::Cos(camRot) * 0.8f;
float camRotSin = Math::Sin(camRot) * 0.8f;
Matrix rotation(
@@ -301,8 +301,8 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input,
data.LensDirtIntensity = 0;
}
data.PostExposure = Math::Exp2(settings.EyeAdaptation.PostExposure);
data.InputSize = Vector2(static_cast<float>(w1), static_cast<float>(h1));
data.InvInputSize = Vector2(1.0f / static_cast<float>(w1), 1.0f / static_cast<float>(h1));
data.InputSize = Float2(static_cast<float>(w1), static_cast<float>(h1));
data.InvInputSize = Float2(1.0f / static_cast<float>(w1), 1.0f / static_cast<float>(h1));
data.InputAspect = static_cast<float>(w1) / h1;
context->UpdateCB(cb0, &data);
context->BindCB(0, cb0);

View File

@@ -21,10 +21,10 @@ private:
float BloomMagnitude;
float BloomBlurSigma;
Vector3 VignetteColor;
Float3 VignetteColor;
float VignetteShapeFactor;
Vector2 InputSize;
Float2 InputSize;
float InputAspect;
float GrainAmount;
@@ -38,11 +38,11 @@ private:
float GhostDispersal;
float LensFlareIntensity;
Vector2 LensInputDistortion;
Float2 LensInputDistortion;
float LensScale;
float LensBias;
Vector2 InvInputSize;
Float2 InvInputSize;
float ChromaticDistortion;
float Time;
@@ -57,10 +57,10 @@ private:
});
PACK_STRUCT(struct GaussianBlurData {
Vector2 Size;
Float2 Size;
float Dummy3;
float Dummy4;
Vector4 GaussianBlurCache[GB_KERNEL_SIZE]; // x-weight, y-offset
Float4 GaussianBlurCache[GB_KERNEL_SIZE]; // x-weight, y-offset
});
// Post Processing
@@ -73,8 +73,8 @@ private:
GPUPipelineStatePermutationsPs<3> _psComposite;
GaussianBlurData _gbData;
Vector4 GaussianBlurCacheH[GB_KERNEL_SIZE];
Vector4 GaussianBlurCacheV[GB_KERNEL_SIZE];
Float4 GaussianBlurCacheH[GB_KERNEL_SIZE];
Float4 GaussianBlurCacheV[GB_KERNEL_SIZE];
AssetReference<Texture> _defaultLensColor;
AssetReference<Texture> _defaultLensStar;

View File

@@ -88,14 +88,14 @@ protected:
PACK_STRUCT(struct Data
{
Vector2 Dummy0;
Float2 Dummy0;
int32 CubeFace;
int32 SourceMipIndex;
Vector4 Sample01;
Vector4 Sample23;
Vector4 CoefficientMask0;
Vector4 CoefficientMask1;
Vector3 Dummy1;
Float4 Sample01;
Float4 Sample23;
Float4 CoefficientMask0;
Float4 CoefficientMask1;
Float3 Dummy1;
float CoefficientMask2;
});
@@ -429,10 +429,10 @@ bool fixFarPlaneTreeExecute(Actor* actor, const Vector3& position, float& farPla
{
if (auto* pointLight = dynamic_cast<PointLight*>(actor))
{
const float dst = Vector3::Distance(pointLight->GetPosition(), position) + pointLight->GetScaledRadius();
const Real dst = Vector3::Distance(pointLight->GetPosition(), position) + pointLight->GetScaledRadius();
if (dst > farPlane)
{
farPlane = dst;
farPlane = (float)dst;
}
}

View File

@@ -415,7 +415,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light
if (!probe->HasProbeLoaded())
continue;
float probeRadius = probe->GetScaledRadius();
Vector3 probePosition = probe->GetPosition();
Vector3 probePosition = probe->GetPosition(); // TODO: large-worlds
// Get distance from view center to light center less radius (check if view is inside a sphere)
const float sphereModelScale = 2.0f;

View File

@@ -49,7 +49,7 @@ void RendererDirectionalLightData::SetupLightData(LightData* data, bool useShado
data->SourceLength = 0;
data->Color = Color;
data->MinRoughness = Math::Max(MinRoughness, MIN_ROUGHNESS);
data->Position = Vector3::Zero;
data->Position = Float3::Zero;
data->CastShadows = useShadow ? 1.0f : 0.0f;
data->Direction = -Direction;
data->Radius = 0;
@@ -102,7 +102,7 @@ void RendererSkyLightData::SetupLightData(LightData* data, bool useShadow) const
data->MinRoughness = MIN_ROUGHNESS;
data->Position = Position;
data->CastShadows = useShadow ? 1.0f : 0.0f;
data->Direction = Vector3::Forward;
data->Direction = Float3::Forward;
data->Radius = Radius;
data->FalloffExponent = 0;
data->InverseSquared = 0;
@@ -388,7 +388,7 @@ void RenderList::Init(RenderContext& renderContext)
{
renderContext.View.Frustum.GetCorners(FrustumCornersWs);
for (int32 i = 0; i < 8; i++)
Vector3::Transform(FrustumCornersWs[i], renderContext.View.View, FrustumCornersVs[i]);
Float3::Transform(FrustumCornersWs[i], renderContext.View.View, FrustumCornersVs[i]);
}
void RenderList::Clear()
@@ -477,7 +477,8 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD
PROFILE_CPU();
const int32 listSize = (int32)list.Indices.Count();
const Plane plane(renderContext.View.Position, renderContext.View.Direction);
const Float3 planeNormal = renderContext.View.Direction;
const float planePoint = -Float3::Dot(planeNormal, renderContext.View.Position);
// Peek shared memory
#define PREPARE_CACHE(list) (list).Clear(); (list).Resize(listSize)
@@ -492,7 +493,7 @@ void RenderList::SortDrawCalls(const RenderContext& renderContext, bool reverseD
for (int32 i = 0; i < listSize; i++)
{
auto& drawCall = DrawCalls[list.Indices[i]];
const auto distance = CollisionsHelper::DistancePlanePoint(plane, drawCall.ObjectPosition);
const float distance = Float3::Dot(planeNormal, drawCall.ObjectPosition) - planePoint;
const uint32 sortKey = RenderTools::ComputeDistanceSortKey(distance) ^ sortKeyXor;
int32 batchKey = GetHash(drawCall.Geometry.IndexBuffer);
batchKey = (batchKey * 397) ^ GetHash(drawCall.Geometry.VertexBuffers[0]);
@@ -771,13 +772,13 @@ DRAW:
auto& instance = batch.Instances[j];
drawCall.ObjectPosition = instance.InstanceOrigin;
drawCall.PerInstanceRandom = instance.PerInstanceRandom;
auto lightmapArea = instance.InstanceLightmapArea.ToVector4();
auto lightmapArea = instance.InstanceLightmapArea.ToFloat4();
drawCall.Surface.LightmapUVsArea = *(Rectangle*)&lightmapArea;
drawCall.Surface.LODDitherFactor = instance.LODDitherFactor;
drawCall.World.SetRow1(Vector4(instance.InstanceTransform1, 0.0f));
drawCall.World.SetRow2(Vector4(instance.InstanceTransform2, 0.0f));
drawCall.World.SetRow3(Vector4(instance.InstanceTransform3, 0.0f));
drawCall.World.SetRow4(Vector4(instance.InstanceOrigin, 1.0f));
drawCall.World.SetRow1(Float4(instance.InstanceTransform1, 0.0f));
drawCall.World.SetRow2(Float4(instance.InstanceTransform2, 0.0f));
drawCall.World.SetRow3(Float4(instance.InstanceTransform3, 0.0f));
drawCall.World.SetRow4(Float4(instance.InstanceOrigin, 1.0f));
drawCall.Material->Bind(bindParams);
context->BindIB(drawCall.Geometry.IndexBuffer);
@@ -824,11 +825,11 @@ bool SurfaceDrawCallHandler::CanBatch(const DrawCall& a, const DrawCall& b)
void SurfaceDrawCallHandler::WriteDrawCall(InstanceData* instanceData, const DrawCall& drawCall)
{
instanceData->InstanceOrigin = Vector3(drawCall.World.M41, drawCall.World.M42, drawCall.World.M43);
instanceData->InstanceOrigin = Float3(drawCall.World.M41, drawCall.World.M42, drawCall.World.M43);
instanceData->PerInstanceRandom = drawCall.PerInstanceRandom;
instanceData->InstanceTransform1 = Vector3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13);
instanceData->InstanceTransform1 = Float3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13);
instanceData->LODDitherFactor = drawCall.Surface.LODDitherFactor;
instanceData->InstanceTransform2 = Vector3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23);
instanceData->InstanceTransform3 = Vector3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33);
instanceData->InstanceTransform2 = Float3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23);
instanceData->InstanceTransform3 = Float3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33);
instanceData->InstanceLightmapArea = Half4(drawCall.Surface.LightmapUVsArea);
}

View File

@@ -20,13 +20,13 @@ struct RenderContext;
struct RendererDirectionalLightData
{
Vector3 Position;
Float3 Position;
float MinRoughness;
Vector3 Color;
Float3 Color;
float ShadowsStrength;
Vector3 Direction;
Float3 Direction;
float ShadowsFadeDistance;
float ShadowsNormalOffsetScale;
@@ -47,13 +47,13 @@ struct RendererDirectionalLightData
struct RendererSpotLightData
{
Vector3 Position;
Float3 Position;
float MinRoughness;
Vector3 Color;
Float3 Color;
float ShadowsStrength;
Vector3 Direction;
Float3 Direction;
float ShadowsFadeDistance;
float ShadowsNormalOffsetScale;
@@ -66,7 +66,7 @@ struct RendererSpotLightData
float FallOffExponent;
float SourceRadius;
Vector3 UpVector;
Float3 UpVector;
float OuterConeAngle;
float CosOuterCone;
@@ -85,13 +85,13 @@ struct RendererSpotLightData
struct RendererPointLightData
{
Vector3 Position;
Float3 Position;
float MinRoughness;
Vector3 Color;
Float3 Color;
float ShadowsStrength;
Vector3 Direction;
Float3 Direction;
float ShadowsFadeDistance;
float ShadowsNormalOffsetScale;
@@ -119,13 +119,13 @@ struct RendererPointLightData
struct RendererSkyLightData
{
Vector3 Position;
Float3 Position;
float VolumetricScatteringIntensity;
Vector3 Color;
Float3 Color;
float Radius;
Vector3 AdditiveColor;
Float3 AdditiveColor;
int8 CastVolumetricShadow : 1;
int8 RenderedVolumetricFog : 1;
@@ -446,12 +446,12 @@ public:
/// <summary>
/// Camera frustum corners in World Space
/// </summary>
Vector3 FrustumCornersWs[8];
Float3 FrustumCornersWs[8];
/// <summary>
/// Camera frustum corners in View Space
/// </summary>
Vector3 FrustumCornersVs[8];
Float3 FrustumCornersVs[8];
private:
@@ -590,12 +590,12 @@ public:
/// </summary>
struct FLAXENGINE_API InstanceData
{
Vector3 InstanceOrigin;
Float3 InstanceOrigin;
float PerInstanceRandom;
Vector3 InstanceTransform1;
Float3 InstanceTransform1;
float LODDitherFactor;
Vector3 InstanceTransform2;
Vector3 InstanceTransform3;
Float3 InstanceTransform2;
Float3 InstanceTransform3;
Half4 InstanceLightmapArea;
};

View File

@@ -32,7 +32,7 @@ PACK_STRUCT(struct Data
float MaxTraceSamples;
float RoughnessFade;
Vector2 SSRtexelSize;
Float2 SSRtexelSize;
float TemporalTime;
float BRDFBias;

View File

@@ -22,7 +22,7 @@ PACK_STRUCT(struct Data{
LightShadowData LightShadow;
Matrix WVP;
Matrix ViewProjectionMatrix;
Vector2 Dummy0;
Float2 Dummy0;
float ContactShadowsDistance;
float ContactShadowsLength;
});
@@ -206,8 +206,8 @@ void ShadowsPass::Dispose()
bool ShadowsPass::CanRenderShadow(RenderContext& renderContext, const RendererPointLightData& light)
{
const Vector3 lightPosition = light.Position;
const float dstLightToView = Vector3::Distance(lightPosition, renderContext.View.Position);
const Float3 lightPosition = light.Position;
const float dstLightToView = Float3::Distance(lightPosition, renderContext.View.Position);
// Fade shadow on distance
const float fadeDistance = Math::Max(light.ShadowsFadeDistance, 0.1f);
@@ -218,8 +218,8 @@ bool ShadowsPass::CanRenderShadow(RenderContext& renderContext, const RendererPo
bool ShadowsPass::CanRenderShadow(RenderContext& renderContext, const RendererSpotLightData& light)
{
const Vector3 lightPosition = light.Position;
const float dstLightToView = Vector3::Distance(lightPosition, renderContext.View.Position);
const Float3 lightPosition = light.Position;
const float dstLightToView = Float3::Distance(lightPosition, renderContext.View.Position);
// Fade shadow on distance
const float fadeDistance = Math::Max(light.ShadowsFadeDistance, 0.1f);
@@ -273,9 +273,9 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererPointLightD
auto shader = _shader->GetShader();
Data sperLight;
float lightRadius = light.Radius;
Vector3 lightPosition = light.Position;
Vector3 lightDirection = light.Direction;
float dstLightToView = Vector3::Distance(lightPosition, view.Position);
Float3 lightPosition = light.Position;
Float3 lightDirection = light.Direction;
float dstLightToView = Float3::Distance(lightPosition, view.Position);
// TODO: here we can use lower shadows quality based on light distance to view (LOD switching) and per light setting for max quality
int32 shadowQuality = maxShadowsQuality;
@@ -288,7 +288,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererPointLightD
const auto shadowMapsSizeCube = (float)_shadowMapsSizeCube;
context->SetViewportAndScissors(shadowMapsSizeCube, shadowMapsSizeCube);
_shadowContext.View.SetUpCube(PointLight_NearPlane, lightRadius, lightPosition);
_shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Vector2::Zero);
_shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Float2::Zero);
// Render depth to all 6 faces of the cube map
for (int32 faceIndex = 0; faceIndex < 6; faceIndex++)
@@ -333,7 +333,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererPointLightD
sperLight.LightShadow.Bias = light.ShadowsDepthBias;
sperLight.LightShadow.FadeDistance = Math::Max(light.ShadowsFadeDistance, 0.1f);
sperLight.LightShadow.NumCascades = 1;
sperLight.LightShadow.CascadeSplits = Vector4::Zero;
sperLight.LightShadow.CascadeSplits = Float4::Zero;
Matrix::Transpose(view.ViewProjection(), sperLight.ViewProjectionMatrix);
sperLight.ContactShadowsDistance = light.ShadowsDistance;
sperLight.ContactShadowsLength = view.Flags & ViewFlags::ContactShadows ? light.ContactShadowsLength : 0.0f;
@@ -376,9 +376,9 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererSpotLightDa
auto shader = _shader->GetShader();
Data sperLight;
float lightRadius = light.Radius;
Vector3 lightPosition = light.Position;
Vector3 lightDirection = light.Direction;
float dstLightToView = Vector3::Distance(lightPosition, view.Position);
Float3 lightPosition = light.Position;
Float3 lightDirection = light.Direction;
float dstLightToView = Float3::Distance(lightPosition, view.Position);
// TODO: here we can use lower shadows quality based on light distance to view (LOD switching) and per light setting for max quality
int32 shadowQuality = maxShadowsQuality;
@@ -391,7 +391,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererSpotLightDa
const auto shadowMapsSizeCube = (float)_shadowMapsSizeCube;
context->SetViewportAndScissors(shadowMapsSizeCube, shadowMapsSizeCube);
_shadowContext.View.SetProjector(SpotLight_NearPlane, lightRadius, lightPosition, lightDirection, light.UpVector, light.OuterConeAngle * 2.0f);
_shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Vector2::Zero);
_shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCube, shadowMapsSizeCube, Float2::Zero);
// Render depth to all 1 face of the cube map
const int32 cubeFaceIndex = 0;
@@ -435,7 +435,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererSpotLightDa
sperLight.LightShadow.Bias = light.ShadowsDepthBias;
sperLight.LightShadow.FadeDistance = Math::Max(light.ShadowsFadeDistance, 0.1f);
sperLight.LightShadow.NumCascades = 1;
sperLight.LightShadow.CascadeSplits = Vector4::Zero;
sperLight.LightShadow.CascadeSplits = Float4::Zero;
Matrix::Transpose(view.ViewProjection(), sperLight.ViewProjectionMatrix);
sperLight.ContactShadowsDistance = light.ShadowsDistance;
sperLight.ContactShadowsLength = view.Flags & ViewFlags::ContactShadows ? light.ContactShadowsLength : 0.0f;
@@ -476,7 +476,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional
auto mainCache = renderContext.List;
auto shader = _shader->GetShader();
Data sperLight;
Vector3 lightDirection = light.Direction;
Float3 lightDirection = light.Direction;
float shadowsDistance = Math::Min(view.Far, light.ShadowsDistance);
int32 csmCount = Math::Clamp(light.CascadeCount, 0, MAX_CSM_CASCADES);
bool blendCSM = Graphics::AllowCSMBlending;
@@ -566,28 +566,28 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional
}
// Select best Up vector
Vector3 side = Vector3::UnitX;
Vector3 upDirection = Vector3::UnitX;
Vector3 VectorUps[] = { Vector3::UnitY, Vector3::UnitX, Vector3::UnitZ };
for (int32 i = 0; i < ARRAY_COUNT(VectorUps); i++)
Float3 side = Float3::UnitX;
Float3 upDirection = Float3::UnitX;
Float3 vectorUps[] = { Float3::UnitY, Float3::UnitX, Float3::UnitZ };
for (int32 i = 0; i < ARRAY_COUNT(vectorUps); i++)
{
const Vector3 vectorUp = VectorUps[i];
if (Math::Abs(Vector3::Dot(lightDirection, vectorUp)) < (1.0f - 0.0001f))
const Float3 vectorUp = vectorUps[i];
if (Math::Abs(Float3::Dot(lightDirection, vectorUp)) < (1.0f - 0.0001f))
{
side = Vector3::Normalize(Vector3::Cross(vectorUp, lightDirection));
upDirection = Vector3::Normalize(Vector3::Cross(lightDirection, side));
side = Float3::Normalize(Float3::Cross(vectorUp, lightDirection));
upDirection = Float3::Normalize(Float3::Cross(lightDirection, side));
break;
}
}
// Temporary data
Vector3 frustumCorners[8];
Float3 frustumCorners[8];
Matrix shadowView, shadowProjection, shadowVP;
// Set up GPU context and render view
const auto shadowMapsSizeCSM = (float)_shadowMapsSizeCSM;
context->SetViewportAndScissors(shadowMapsSizeCSM, shadowMapsSizeCSM);
_shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCSM, shadowMapsSizeCSM, Vector2::Zero);
_shadowContext.View.PrepareCache(_shadowContext, shadowMapsSizeCSM, shadowMapsSizeCSM, Float2::Zero);
// Create the different view and projection matrices for each split
float splitMinRatio = 0;
@@ -618,26 +618,27 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional
ViewSnapping,
};
const StabilizationMode stabilization = ViewSnapping; // TODO: expose to graphics settings maybe
Vector3 cascadeMinBoundLS;
Vector3 cascadeMaxBoundLS;
Vector3 target;
Float3 cascadeMinBoundLS;
Float3 cascadeMaxBoundLS;
Float3 target;
{
// Make sure we are using the same direction when stabilizing
BoundingSphere boundingVS;
BoundingSphere::FromPoints(frustumCorners, ARRAY_COUNT(frustumCorners), boundingVS);
// Compute bounding box center
Vector3::TransformCoordinate(boundingVS.Center, view.IV, target);
cascadeMaxBoundLS = Vector3(boundingVS.Radius);
Float3::TransformCoordinate(boundingVS.Center, view.IV, target);
float boundingVSRadius = (float)boundingVS.Radius;
cascadeMaxBoundLS = Float3(boundingVSRadius);
cascadeMinBoundLS = -cascadeMaxBoundLS;
if (stabilization == ViewSnapping)
{
// Snap the target to the texel units (reference: ShaderX7 - Practical Cascaded Shadows Maps)
float shadowMapHalfSize = shadowMapsSizeCSM * 0.5f;
float x = Math::Ceil(Vector3::Dot(target, upDirection) * shadowMapHalfSize / boundingVS.Radius) * boundingVS.Radius / shadowMapHalfSize;
float y = Math::Ceil(Vector3::Dot(target, side) * shadowMapHalfSize / boundingVS.Radius) * boundingVS.Radius / shadowMapHalfSize;
float z = Vector3::Dot(target, lightDirection);
float x = Math::Ceil(Float3::Dot(target, upDirection) * shadowMapHalfSize / boundingVSRadius) * boundingVSRadius / shadowMapHalfSize;
float y = Math::Ceil(Float3::Dot(target, side) * shadowMapHalfSize / boundingVSRadius) * boundingVSRadius / shadowMapHalfSize;
float z = Float3::Dot(target, lightDirection);
target = upDirection * x + side * y + lightDirection * z;
}
}
@@ -665,10 +666,10 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional
// Stabilize the shadow matrix on the projection
if (stabilization == ProjectionSnapping)
{
Vector3 shadowPixelPosition = shadowVP.GetTranslation() * (shadowMapsSizeCSM * 0.5f);
Float3 shadowPixelPosition = shadowVP.GetTranslation() * (shadowMapsSizeCSM * 0.5f);
shadowPixelPosition.Z = 0;
const Vector3 shadowPixelPositionRounded(Math::Round(shadowPixelPosition.X), Math::Round(shadowPixelPosition.Y), 0.0f);
const Vector4 shadowPixelOffset((shadowPixelPositionRounded - shadowPixelPosition) * (2.0f / shadowMapsSizeCSM), 0.0f);
const Float3 shadowPixelPositionRounded(Math::Round(shadowPixelPosition.X), Math::Round(shadowPixelPosition.Y), 0.0f);
const Float4 shadowPixelOffset((shadowPixelPositionRounded - shadowPixelPosition) * (2.0f / shadowMapsSizeCSM), 0.0f);
shadowProjection.SetRow4(shadowProjection.GetRow4() + shadowPixelOffset);
Matrix::Multiply(shadowView, shadowProjection, shadowVP);
}
@@ -727,7 +728,7 @@ void ShadowsPass::RenderShadow(RenderContext& renderContext, RendererDirectional
sperLight.LightShadow.Bias = light.ShadowsDepthBias;
sperLight.LightShadow.FadeDistance = Math::Max(light.ShadowsFadeDistance, 0.1f);
sperLight.LightShadow.NumCascades = csmCount;
sperLight.LightShadow.CascadeSplits = view.Near + Vector4(cascadeSplits) * cameraRange;
sperLight.LightShadow.CascadeSplits = view.Near + Float4(cascadeSplits) * cameraRange;
Matrix::Transpose(view.ViewProjection(), sperLight.ViewProjectionMatrix);
sperLight.ContactShadowsDistance = light.ShadowsDistance;
sperLight.ContactShadowsLength = view.Flags & ViewFlags::ContactShadows ? light.ContactShadowsLength : 0.0f;

View File

@@ -5,8 +5,8 @@
#include "Engine/Content/Content.h"
PACK_STRUCT(struct Data {
Vector2 TexelSize;
Vector2 Padding;
Float2 TexelSize;
Float2 Padding;
});
String MultiScaler::ToString() const

View File

@@ -182,7 +182,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context,
// Prepare
const int32 width = renderContext.Buffers->GetWidth();
const int32 height = renderContext.Buffers->GetHeight();
_cache.GridSize = Vector3(
_cache.GridSize = Float3(
(float)Math::DivideAndRoundUp(width, _cache.GridPixelSize),
(float)Math::DivideAndRoundUp(height, _cache.GridPixelSize),
(float)_cache.GridSizeZ);
@@ -191,9 +191,9 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context,
// Init data (partial, without directional light or sky light data);
GBufferPass::SetInputs(renderContext.View, _cache.Data.GBuffer);
_cache.Data.GlobalAlbedo = options.Albedo.ToVector3() * options.Albedo.A;
_cache.Data.GlobalAlbedo = options.Albedo.ToFloat3() * options.Albedo.A;
_cache.Data.GlobalExtinctionScale = options.ExtinctionScale;
_cache.Data.GlobalEmissive = options.Emissive.ToVector3() * options.Emissive.A;
_cache.Data.GlobalEmissive = options.Emissive.ToFloat3() * options.Emissive.A;
_cache.Data.GridSize = _cache.GridSize;
_cache.Data.GridSizeIntX = (uint32)_cache.GridSize.X;
_cache.Data.GridSizeIntY = (uint32)_cache.GridSize.Y;
@@ -209,7 +209,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context,
_cache.Data.SkyLight.VolumetricScatteringIntensity = 0;
// Fill frame jitter history
const Vector4 defaultOffset = Vector4(0.5f, 0.5f, 0.5f, 0.0f);
const Float4 defaultOffset(0.5f, 0.5f, 0.5f, 0.0f);
for (int32 i = 0; i < ARRAY_COUNT(_cache.Data.FrameJitterOffsets); i++)
{
_cache.Data.FrameJitterOffsets[i] = defaultOffset;
@@ -219,7 +219,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context,
for (int32 i = 0; i < _cache.MissedHistorySamplesCount; i++)
{
const uint64 frameNumber = renderContext.Task->LastUsedFrame - i;
_cache.Data.FrameJitterOffsets[i] = Vector4(
_cache.Data.FrameJitterOffsets[i] = Float4(
RendererUtils::TemporalHalton(frameNumber & 1023, 2),
RendererUtils::TemporalHalton(frameNumber & 1023, 3),
RendererUtils::TemporalHalton(frameNumber & 1023, 5),
@@ -234,7 +234,7 @@ bool VolumetricFogPass::Init(RenderContext& renderContext, GPUContext* context,
// Clear local lights scattering table if was used and will be probably reused later
if (renderContext.Buffers->LocalShadowedLightScattering)
{
if (Vector3::NearEqual(renderContext.Buffers->LocalShadowedLightScattering->Size3(), _cache.GridSize))
if (Float3::NearEqual(renderContext.Buffers->LocalShadowedLightScattering->Size3(), _cache.GridSize))
{
context->Clear(renderContext.Buffers->LocalShadowedLightScattering->ViewVolume(), Color::Transparent);
}
@@ -274,15 +274,16 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte
auto& view = renderContext.View;
// Calculate light volume bounds in camera frustum depth range (min and max)
BoundingSphere bounds(light.Position, light.Radius);
Vector3 viewSpaceLightBoundsOrigin = Vector3::Transform(bounds.Center, view.View);
float furthestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z + bounds.Radius, options, _cache.GridSizeZ);
float closestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z - bounds.Radius, options, _cache.GridSizeZ);
const Float3 center = light.Position;
const float radius = light.Radius;
Float3 viewSpaceLightBoundsOrigin = Float3::Transform(center, view.View);
float furthestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z + radius, options, _cache.GridSizeZ);
float closestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z - radius, options, _cache.GridSizeZ);
int32 volumeZBoundsMin = (int32)Math::Clamp(closestSliceIndexUnclamped, 0.0f, _cache.GridSize.Z - 1.0f);
int32 volumeZBoundsMax = (int32)Math::Clamp(furthestSliceIndexUnclamped, 0.0f, _cache.GridSize.Z - 1.0f);
// Cull light
if ((view.Position - bounds.Center).LengthSquared() >= (options.Distance + bounds.Radius) * (options.Distance + bounds.Radius) || volumeZBoundsMin >= volumeZBoundsMax)
if ((view.Position - center).LengthSquared() >= (options.Distance + radius) * (options.Distance + radius) || volumeZBoundsMin >= volumeZBoundsMax)
return;
PROFILE_GPU_CPU("Volumetric Fog Light");
@@ -304,7 +305,7 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte
perLight.SliceToDepth.Y = _cache.Data.VolumetricFogMaxDistance;
perLight.MinZ = volumeZBoundsMin;
perLight.LocalLightScatteringIntensity = light.VolumetricScatteringIntensity;
perLight.ViewSpaceBoundingSphere = Vector4(viewSpaceLightBoundsOrigin, bounds.Radius);
perLight.ViewSpaceBoundingSphere = Float4(viewSpaceLightBoundsOrigin, radius);
Matrix::Transpose(view.Projection, perLight.ViewToVolumeClip);
light.SetupLightData(&perLight.LocalLight, true);
perLight.LocalLightShadow = shadow;
@@ -343,13 +344,15 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte
template<typename T>
void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUContext* context, RenderView& view, VolumetricFogOptions& options, T& light, PerLight& perLight, GPUConstantBuffer* cb1)
{
const BoundingSphere bounds(light.Position, light.Radius);
const Float3 center = light.Position;
const float radius = light.Radius;
ASSERT(!center.IsNanOrInfinity() && !isnan(radius) && !isinf(radius));
auto& cache = _cache;
// Calculate light volume bounds in camera frustum depth range (min and max)
const Vector3 viewSpaceLightBoundsOrigin = Vector3::Transform(bounds.Center, view.View);
const float furthestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z + bounds.Radius, options, cache.GridSizeZ);
const float closestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z - bounds.Radius, options, cache.GridSizeZ);
const Float3 viewSpaceLightBoundsOrigin = Float3::Transform(center, view.View);
const float furthestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z + radius, options, cache.GridSizeZ);
const float closestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z - radius, options, cache.GridSizeZ);
const int32 volumeZBoundsMin = (int32)Math::Clamp(closestSliceIndexUnclamped, 0.0f, cache.GridSize.Z - 1.0f);
const int32 volumeZBoundsMax = (int32)Math::Clamp(furthestSliceIndexUnclamped, 0.0f, cache.GridSize.Z - 1.0f);
@@ -363,7 +366,7 @@ void VolumetricFogPass::RenderRadialLight(RenderContext& renderContext, GPUConte
perLight.SliceToDepth.Y = cache.Data.VolumetricFogMaxDistance;
perLight.MinZ = volumeZBoundsMin;
perLight.LocalLightScatteringIntensity = light.VolumetricScatteringIntensity;
perLight.ViewSpaceBoundingSphere = Vector4(viewSpaceLightBoundsOrigin, bounds.Radius);
perLight.ViewSpaceBoundingSphere = Float4(viewSpaceLightBoundsOrigin, radius);
Matrix::Transpose(renderContext.View.Projection, perLight.ViewToVolumeClip);
light.SetupLightData(&perLight.LocalLight, withShadow);
@@ -480,7 +483,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext)
const bool temporalHistoryIsValid = cache.TemporalReprojection
&& renderContext.Buffers->VolumetricFogHistory
&& !renderContext.Task->IsCameraCut
&& Vector3::NearEqual(renderContext.Buffers->VolumetricFogHistory->Size3(), cache.GridSize);
&& Float3::NearEqual(renderContext.Buffers->VolumetricFogHistory->Size3(), cache.GridSize);
// Allocate buffers
const GPUTextureDescription volumeDesc = GPUTextureDescription::New3D(cache.GridSize, PixelFormat::R16G16B16A16_Float, GPUTextureFlags::RenderTarget | GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess);
@@ -530,18 +533,19 @@ void VolumetricFogPass::Render(RenderContext& renderContext)
for (auto& drawCall : renderContext.List->VolumetricFogParticles)
{
const BoundingSphere bounds(drawCall.Particle.VolumetricFog.Position, drawCall.Particle.VolumetricFog.Radius);
ASSERT(!bounds.Center.IsNanOrInfinity() && !isnan(bounds.Radius) && !isinf(bounds.Radius));
const Float3 center = drawCall.Particle.VolumetricFog.Position;
const float radius = drawCall.Particle.VolumetricFog.Radius;
ASSERT(!center.IsNanOrInfinity() && !isnan(radius) && !isinf(radius));
// Calculate light volume bounds in camera frustum depth range (min and max)
const Vector3 viewSpaceLightBoundsOrigin = Vector3::Transform(bounds.Center, view.View);
const float furthestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z + bounds.Radius, options, cache.GridSizeZ);
const float closestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z - bounds.Radius, options, cache.GridSizeZ);
const Float3 viewSpaceLightBoundsOrigin = Float3::Transform(center, view.View);
const float furthestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z + radius, options, cache.GridSizeZ);
const float closestSliceIndexUnclamped = ComputeZSliceFromDepth(viewSpaceLightBoundsOrigin.Z - radius, options, cache.GridSizeZ);
const int32 volumeZBoundsMin = (int32)Math::Clamp(closestSliceIndexUnclamped, 0.0f, cache.GridSize.Z - 1.0f);
const int32 volumeZBoundsMax = (int32)Math::Clamp(furthestSliceIndexUnclamped, 0.0f, cache.GridSize.Z - 1.0f);
// Culling
if ((view.Position - bounds.Center).LengthSquared() >= (options.Distance + bounds.Radius) * (options.Distance + bounds.Radius) || volumeZBoundsMin >= volumeZBoundsMax)
if ((view.Position - center).LengthSquared() >= (options.Distance + radius) * (options.Distance + radius) || volumeZBoundsMin >= volumeZBoundsMax)
continue;
// Setup material shader data
@@ -555,7 +559,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext)
perLight.SliceToDepth.X = cache.Data.GridSize.Z;
perLight.SliceToDepth.Y = cache.Data.VolumetricFogMaxDistance;
perLight.MinZ = volumeZBoundsMin;
perLight.ViewSpaceBoundingSphere = Vector4(viewSpaceLightBoundsOrigin, bounds.Radius);
perLight.ViewSpaceBoundingSphere = Float4(viewSpaceLightBoundsOrigin, radius);
Matrix::Transpose(renderContext.View.Projection, perLight.ViewToVolumeClip);
// Upload data
@@ -672,7 +676,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext)
// Get buffer for the integrated light scattering (try to reuse the previous frame if it's valid)
GPUTexture* integratedLightScattering = renderContext.Buffers->VolumetricFog;
if (integratedLightScattering == nullptr || !Vector3::NearEqual(integratedLightScattering->Size3(), cache.GridSize))
if (integratedLightScattering == nullptr || !Float3::NearEqual(integratedLightScattering->Size3(), cache.GridSize))
{
if (integratedLightScattering)
{
@@ -710,14 +714,14 @@ void VolumetricFogPass::InitCircleBuffer()
const int32 triangles = vertices - 2;
const int32 rings = vertices;
const float radiansPerRingSegment = PI / (float)rings;
Vector2 vbData[vertices];
Float2 vbData[vertices];
uint16 ibData[triangles * 3];
const float radiusScale = 1.0f / Math::Cos(radiansPerRingSegment);
for (int32 vertexIndex = 0; vertexIndex < vertices; vertexIndex++)
{
const float angle = vertexIndex / static_cast<float>(vertices - 1) * 2 * PI;
vbData[vertexIndex] = Vector2(radiusScale * Math::Cos(angle) * 0.5f + 0.5f, radiusScale * Math::Sin(angle) * 0.5f + 0.5f);
vbData[vertexIndex] = Float2(radiusScale * Math::Cos(angle) * 0.5f + 0.5f, radiusScale * Math::Sin(angle) * 0.5f + 0.5f);
}
int32 ibIndex = 0;
for (int32 triangleIndex = 0; triangleIndex < triangles; triangleIndex++)
@@ -732,7 +736,7 @@ void VolumetricFogPass::InitCircleBuffer()
ASSERT(_vbCircleRasterize == nullptr && _ibCircleRasterize == nullptr);
_vbCircleRasterize = GPUDevice::Instance->CreateBuffer(TEXT("VolumetricFog.CircleRasterize.VB"));
_ibCircleRasterize = GPUDevice::Instance->CreateBuffer(TEXT("VolumetricFog.CircleRasterize.IB"));
if (_vbCircleRasterize->Init(GPUBufferDescription::Vertex(sizeof(Vector2), vertices, vbData))
if (_vbCircleRasterize->Init(GPUBufferDescription::Vertex(sizeof(Float2), vertices, vbData))
|| _ibCircleRasterize->Init(GPUBufferDescription::Index(sizeof(uint16), triangles * 3, ibData)))
{
LOG(Fatal, "Failed to setup volumetric fog buffers.");

View File

@@ -20,7 +20,7 @@ public:
struct CustomData
{
GPUShader* Shader;
Vector3 GridSize;
Float3 GridSize;
float VolumetricFogMaxDistance;
int32 ParticleIndex;
};
@@ -28,22 +28,22 @@ public:
private:
PACK_STRUCT(struct SkyLightData {
Vector3 MultiplyColor;
Float3 MultiplyColor;
float VolumetricScatteringIntensity;
Vector3 AdditiveColor;
Float3 AdditiveColor;
float Dummt0;
});
PACK_STRUCT(struct Data {
GBufferData GBuffer;
Vector3 GlobalAlbedo;
Float3 GlobalAlbedo;
float GlobalExtinctionScale;
Vector3 GlobalEmissive;
Float3 GlobalEmissive;
float HistoryWeight;
Vector3 GridSize;
Float3 GridSize;
uint32 MissedHistorySamplesCount;
uint32 GridSizeIntX;
@@ -51,15 +51,15 @@ private:
uint32 GridSizeIntZ;
float PhaseG;
Vector2 Dummy0;
Float2 Dummy0;
float VolumetricFogMaxDistance;
float InverseSquaredLightDistanceBiasScale;
Vector4 FogParameters;
Float4 FogParameters;
Matrix PrevWorldToClip;
Vector4 FrameJitterOffsets[8];
Float4 FrameJitterOffsets[8];
LightData DirectionalLight;
LightShadowData DirectionalLightShadow;
@@ -67,11 +67,11 @@ private:
});
PACK_STRUCT(struct PerLight {
Vector2 SliceToDepth;
Float2 SliceToDepth;
int32 MinZ;
float LocalLightScatteringIntensity;
Vector4 ViewSpaceBoundingSphere;
Float4 ViewSpaceBoundingSphere;
Matrix ViewToVolumeClip;
LightData LocalLight;
@@ -131,7 +131,7 @@ private:
/// <summary>
/// The calculated size of the volume texture.
/// </summary>
Vector3 GridSize;
Float3 GridSize;
/// <summary>
/// The cached per-frame data for the constant buffer.