Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified Content/Materials/Layers/ML_CesiumVoxel.uasset
Binary file not shown.
69 changes: 59 additions & 10 deletions Shaders/Private/CesiumVoxelTemplate.usf
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,37 @@ struct VoxelMegatextures
uint3 PaddingBefore;
uint3 PaddingAfter;

bool UseLinearInterpolation;

int3 TileIndexToCoords(in int Index)
{
if (TileCount.x == 0 || TileCount.y == 0 || TileCount.z == 0)
{
return 0;
}

int ZSlice = TileCount.x * TileCount.y;
int Z = Index / ZSlice;
int Y = (Index % ZSlice) / TileCount.x;
int X = Index % TileCount.x;
return int3(X, Y, Z) * (GridDimensions + PaddingBefore + PaddingAfter);
}

CustomShaderProperties GetPropertiesAtCoords(int3 Coords)
{
CustomShaderProperties Properties = (CustomShaderProperties) 0;
%s

return Properties;
}

CustomShaderProperties InterpolateProperties(CustomShaderProperties A, CustomShaderProperties B, float t)
{
CustomShaderProperties Result = (CustomShaderProperties) 0;
%s

return Result;
}

CustomShaderProperties GetProperties(in TileSample Sample)
{
Expand All @@ -69,6 +88,7 @@ struct VoxelMegatextures
// Compute int coordinates of the voxel within the tile.
float3 LocalUV = Sample.LocalUV;
uint3 DataDimensions = GridDimensions + PaddingBefore + PaddingAfter;
float3 MaxVoxelCoords = float3(DataDimensions - 1u);

if (ShapeConstant == BOX)
{
Expand All @@ -81,18 +101,46 @@ struct VoxelMegatextures
// The start of the angular bounds has to be adjusted for full cylinders (root tile only).
float adjustedAngle = WrapCylinderUV && Sample.Coords.w == 0 ? frac(LocalUV.y + 0.5) : LocalUV.y;
LocalUV = float3(LocalUV.x, LocalUV.z, adjustedAngle);
}

float3 VoxelCoords = floor(LocalUV * float3(GridDimensions));
// Account for padding
VoxelCoords = clamp(VoxelCoords + float3(PaddingBefore), 0, float3(DataDimensions - 1u));

int3 Coords = TileCoords + VoxelCoords;
}

CustomShaderProperties Properties = (CustomShaderProperties) 0;
%s
float3 VoxelCoords = LocalUV * float3(GridDimensions);

return Properties;
if (UseLinearInterpolation)
{
// Account for padding
VoxelCoords += float3(PaddingBefore);

float3 t = frac(VoxelCoords + 0.5);
float3 Coords = TileCoords + VoxelCoords;
int3 MaxCoords = TileCoords + MaxVoxelCoords;

// Linear interpolation must be confined within a tile to avoid sampling data that is not physically adjacent.
// That means we must manually interpolate instead of relying on a linear texture filter.
CustomShaderProperties x0y0z0 = GetPropertiesAtCoords(clamp(floor(Coords + float3(-0.5, -0.5, -0.5)), TileCoords, MaxCoords));
CustomShaderProperties x1y0z0 = GetPropertiesAtCoords(clamp(floor(Coords + float3 (0.5, -0.5, -0.5)), TileCoords, MaxCoords));
CustomShaderProperties x0y1z0 = GetPropertiesAtCoords(clamp(floor(Coords + float3(-0.5, 0.5, -0.5)), TileCoords, MaxCoords));
CustomShaderProperties x1y1z0 = GetPropertiesAtCoords(clamp(floor(Coords + float3( 0.5, 0.5, -0.5)), TileCoords, MaxCoords));
CustomShaderProperties x0y0z1 = GetPropertiesAtCoords(clamp(floor(Coords + float3(-0.5, -0.5, 0.5)), TileCoords, MaxCoords));
CustomShaderProperties x1y0z1 = GetPropertiesAtCoords(clamp(floor(Coords + float3( 0.5, -0.5, 0.5)), TileCoords, MaxCoords));
CustomShaderProperties x0y1z1 = GetPropertiesAtCoords(clamp(floor(Coords + float3(-0.5, 0.5, 0.5)), TileCoords, MaxCoords));
CustomShaderProperties x1y1z1 = GetPropertiesAtCoords(clamp(floor(Coords + float3( 0.5, 0.5, 0.5)), TileCoords, MaxCoords));

CustomShaderProperties y0z0 = InterpolateProperties(x0y0z0, x1y0z0, t.x);
CustomShaderProperties y1z0 = InterpolateProperties(x0y1z0, x1y1z0, t.x);
CustomShaderProperties y0z1 = InterpolateProperties(x0y0z1, x1y0z1, t.x);
CustomShaderProperties y1z1 = InterpolateProperties(x0y1z1, x1y1z1, t.x);

CustomShaderProperties z0 = InterpolateProperties(y0z0, y1z0, t.y);
CustomShaderProperties z1 = InterpolateProperties(y0z1, y1z1, t.y);

return InterpolateProperties(z0, z1, t.z);
}
else
{
// Account for padding
VoxelCoords = clamp(floor(VoxelCoords) + float3(PaddingBefore), 0, MaxVoxelCoords);
return GetPropertiesAtCoords(TileCoords + VoxelCoords);
}
}
};

Expand Down Expand Up @@ -167,6 +215,7 @@ VoxelMegatextures DataTextures;
DataTextures.ShapeConstant = ShapeConstant;
DataTextures.TileCount = TileCount;
DataTextures.WrapCylinderUV = (ShapeConstant == CYLINDER) ? (Octree.GridShape.CylinderShape.AngleRangeFlag == 0) : false;
DataTextures.UseLinearInterpolation = bool(UseLinearInterpolation);

// Account for y-up -> z-up conventions for certain shapes.
switch (ShapeConstant) {
Expand Down
21 changes: 21 additions & 0 deletions Source/CesiumRuntime/Private/Cesium3DTileset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,17 @@ void ACesium3DTileset::SetPointCloudShading(
}
}

void ACesium3DTileset::SetVoxelRenderingOptions(
FCesiumVoxelRenderingOptions InVoxelRenderingOptions) {
if (VoxelRenderingOptions != InVoxelRenderingOptions) {
VoxelRenderingOptions = InVoxelRenderingOptions;
if (this->_pVoxelRendererComponent) {
this->_pVoxelRendererComponent->SetVoxelRenderingOptions(
InVoxelRenderingOptions);
}
}
}

void ACesium3DTileset::SetRuntimeVirtualTextures(
TArray<URuntimeVirtualTexture*> InRuntimeVirtualTextures) {
if (this->RuntimeVirtualTextures != InRuntimeVirtualTextures) {
Expand Down Expand Up @@ -2299,6 +2310,13 @@ void ACesium3DTileset::PostEditChangeChainProperty(
if (PropName ==
GET_MEMBER_NAME_CHECKED(ACesium3DTileset, PointCloudShading)) {
FCesiumGltfPointsSceneProxyUpdater::UpdateSettingsInProxies(this);
} else if (
PropName ==
GET_MEMBER_NAME_CHECKED(ACesium3DTileset, VoxelRenderingOptions)) {
if (this->_pVoxelRendererComponent) {
this->_pVoxelRendererComponent->SetVoxelRenderingOptions(
VoxelRenderingOptions);
}
}
}

Expand Down Expand Up @@ -2411,5 +2429,8 @@ void ACesium3DTileset::createVoxelRenderer(
Warning,
TEXT("Voxel renderer could not be attached to root"));
}

this->_pVoxelRendererComponent->SetVoxelRenderingOptions(
this->VoxelRenderingOptions);
}
}
53 changes: 47 additions & 6 deletions Source/CesiumRuntime/Private/CesiumVoxelMetadataComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ struct MaterialResourceLibrary {
struct CustomShaderBuilder {
FString DeclareShaderProperties;
FString SamplePropertiesFromTexture;
FString InterpolateProperties;
FString DeclareDataTextureVariables;
FString SetDataTextures;

Expand Down Expand Up @@ -429,6 +430,44 @@ struct CustomShaderBuilder {
}
}

/**
* Adds code for linearly interpolating the property in the corresponding
* shader function.
*/
void AddPropertyInterpolation(
const FString& PropertyName,
const FCesiumPropertyAttributePropertyDescription& Property) {
if (!InterpolateProperties.IsEmpty()) {
InterpolateProperties += "\n\t\t";
}

// Example: Result.Property = lerp(A.Property, B.Property, t);
FString lerp = "Result." + PropertyName + " = lerp(A." + PropertyName +
", B." + PropertyName + ", t);\n";

// Any "noData" values should be omitted from inteprolation. Otherwise, they
// may result in nonsensical data.
if (Property.PropertyDetails.bHasNoDataValue) {
FString NoDataName = PropertyName + MaterialPropertyNoDataSuffix;
// Example: if {A.Property == Property_NODATA) {
// Result.Property = B.Property;
// }
// else if (B.Property == Property_NODATA) {
// Result.Property = A.Property;
// } else {
// Result.Property = lerp(A.Property, B.Property, t);
// }
InterpolateProperties +=
"if (A." + PropertyName + " == " + NoDataName + ") {\n\t\t" +
"Result." + PropertyName + " = B." + PropertyName + ";\n}\n\t" +
"else if (B." + PropertyName + " == " + NoDataName + ") {\n\t\t" +
"Result." + PropertyName + " = A." + PropertyName + ";\n}\n\t" +
"else {\n\t\t" + lerp + "}\n";
} else {
InterpolateProperties += lerp;
}
}

/**
* Comprehensively adds the declaration for properties and data textures, as
* well as the code to correctly retrieve the property values from the data
Expand All @@ -441,6 +480,7 @@ struct CustomShaderBuilder {
AddPropertyDeclaration(PropertyName, Property);
AddDataTexture(PropertyName, TextureParameterName);
AddPropertyRetrieval(PropertyName, Property);
AddPropertyInterpolation(PropertyName, Property);
}
};
} // namespace
Expand Down Expand Up @@ -720,12 +760,12 @@ static void GenerateMaterialNodes(
continue;
}

auto* VectorParameterNode =
Cast<UMaterialExpressionVectorParameter>(NewExpression);
if (VectorParameterNode &&
VectorParameterNode->ParameterName.ToString() == "Tile Count") {
DataSectionX = VectorParameterNode->MaterialExpressionEditorX;
DataSectionY = VectorParameterNode->MaterialExpressionEditorY;
auto* ScalarParameterNode =
Cast<UMaterialExpressionScalarParameter>(NewExpression);
if (ScalarParameterNode && ScalarParameterNode->ParameterName.ToString() ==
"Use Linear Interpolation") {
DataSectionX = ScalarParameterNode->MaterialExpressionEditorX;
DataSectionY = ScalarParameterNode->MaterialExpressionEditorY;
}
}

Expand Down Expand Up @@ -831,6 +871,7 @@ static void GenerateMaterialNodes(
LazyPrintf.PushParam(*Component->CustomShader);
LazyPrintf.PushParam(*Builder.DeclareDataTextureVariables);
LazyPrintf.PushParam(*Builder.SamplePropertiesFromTexture);
LazyPrintf.PushParam(*Builder.InterpolateProperties);
LazyPrintf.PushParam(*Builder.SetDataTextures);

RaymarchNode->Code = LazyPrintf.GetResultString();
Expand Down
24 changes: 22 additions & 2 deletions Source/CesiumRuntime/Private/CesiumVoxelRendererComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Engine/Texture.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "PhysicsEngine/BodySetup.h"
#include "SceneInterface.h"
#include "UObject/ConstructorHelpers.h"
#include "VecMath.h"

Expand Down Expand Up @@ -1051,6 +1052,25 @@ UCesiumVoxelRendererComponent::CreateVoxelMaterial(
return pVoxelComponent;
}

void UCesiumVoxelRendererComponent::SetVoxelRenderingOptions(
const FCesiumVoxelRenderingOptions& Options) {
UMaterialInstanceDynamic* pMaterial = nullptr;
if (this->MeshComponent) {
UMaterialInterface* pMaterialInterface =
this->MeshComponent->GetMaterial(0);
pMaterial = Cast<UMaterialInstanceDynamic>(pMaterialInterface);
}

if (pMaterial) {
pMaterial->SetScalarParameterValueByInfo(
FMaterialParameterInfo(
UTF8_TO_TCHAR("Use Linear Interpolation"),
EMaterialParameterAssociation::LayerParameter,
0),
float(Options.EnableLinearInterpolation));
}
}

namespace {
template <typename Func>
void forEachRenderableVoxelTile(const auto& tiles, Func&& f) {
Expand Down Expand Up @@ -1231,8 +1251,8 @@ void UCesiumVoxelRendererComponent::UpdateTiles(

namespace {
/**
* Updates the input voxel material to account for origin shifting or ellipsoid
* changes from the tileset's georeference.
* Updates the input voxel material to account for origin shifting or
* ellipsoid changes from the tileset's georeference.
*/
void updateEllipsoidVoxelParameters(
UMaterialInstanceDynamic* pMaterial,
Expand Down
3 changes: 3 additions & 0 deletions Source/CesiumRuntime/Private/CesiumVoxelRendererComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#pragma once

#include "CesiumVoxelRenderingOptions.h"
#include "Components/SceneComponent.h"
#include "Components/StaticMeshComponent.h"
#include "CoreMinimal.h"
Expand Down Expand Up @@ -90,6 +91,8 @@ class UCesiumVoxelRendererComponent : public USceneComponent {
const std::vector<Cesium3DTilesSelection::Tile::ConstPointer>& VisibleTiles,
const std::vector<double>& VisibleTileScreenSpaceErrors);

void SetVoxelRenderingOptions(const FCesiumVoxelRenderingOptions& Options);

private:
static UMaterialInstanceDynamic* CreateVoxelMaterial(
UCesiumVoxelRendererComponent* pVoxelComponent,
Expand Down
23 changes: 23 additions & 0 deletions Source/CesiumRuntime/Public/Cesium3DTileset.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@
#include "CesiumPointCloudShading.h"
#include "CesiumSampleHeightResult.h"
#include "CesiumVoxelMetadataComponent.h"
#include "CesiumVoxelRenderingOptions.h"
#include "CoreMinimal.h"
#include "CustomDepthParameters.h"
#include "Engine/EngineTypes.h"
#include "GameFramework/Actor.h"
#include "Interfaces/IHttpRequest.h"
#include "PrimitiveSceneProxy.h"

#include <PhysicsEngine/BodyInstance.h>
#include <atomic>
#include <chrono>
#include <glm/mat4x4.hpp>
#include <unordered_map>
#include <vector>

#include "Cesium3DTileset.generated.h"

#ifdef CESIUM_DEBUG_TILE_STATES
Expand Down Expand Up @@ -956,6 +959,17 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor {
Category = "Cesium|Rendering")
FCesiumPointCloudShading PointCloudShading;

/**
* If this tileset contains voxels, their appearance can be configured with
* these voxel rendering parameters.
*/
UPROPERTY(
EditAnywhere,
BlueprintGetter = GetVoxelRenderingOptions,
BlueprintSetter = SetVoxelRenderingOptions,
Category = "Cesium|Rendering")
FCesiumVoxelRenderingOptions VoxelRenderingOptions;

/**
* Array of runtime virtual textures into which we draw the mesh for this
* actor. The material also needs to be set up to output to a virtual texture.
Expand Down Expand Up @@ -1164,6 +1178,15 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor {
UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering")
void SetPointCloudShading(FCesiumPointCloudShading InPointCloudShading);

UFUNCTION(BlueprintGetter, Category = "Cesium|Rendering")
FCesiumVoxelRenderingOptions GetVoxelRenderingOptions() const {
return VoxelRenderingOptions;
}

UFUNCTION(BlueprintSetter, Category = "Cesium|Rendering")
void SetVoxelRenderingOptions(
FCesiumVoxelRenderingOptions InVoxelRenderingOptions);

UFUNCTION(BlueprintCallable, Category = "Cesium|Rendering")
void PlayMovieSequencer();

Expand Down
34 changes: 34 additions & 0 deletions Source/CesiumRuntime/Public/CesiumVoxelRenderingOptions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2020-2024 CesiumGS, Inc. and Contributors

#pragma once

#include "CoreMinimal.h"

#include "CesiumVoxelRenderingOptions.generated.h"

/**
* Options for adjusting how voxels are rendered using 3D Tiles.
*/
USTRUCT(BlueprintType)
struct CESIUMRUNTIME_API FCesiumVoxelRenderingOptions {
GENERATED_USTRUCT_BODY()

/**
* Whether to enable linear interpolation when rendering voxels. This can
* result in a smoother appearance across a large voxel tileset. If false,
* nearest sampling will be used.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Cesium")
bool EnableLinearInterpolation = false;

bool operator==(
const FCesiumVoxelRenderingOptions& OtherVoxelRenderingOptions) const {
return EnableLinearInterpolation ==
OtherVoxelRenderingOptions.EnableLinearInterpolation;
}

bool operator!=(
const FCesiumVoxelRenderingOptions& OtherVoxelRenderingOptions) const {
return !(*this == OtherVoxelRenderingOptions);
}
};
Loading