34935-vm/assets/cesium/packages/engine/Source/Scene/processVoxelProperties.js
Flatlogic Bot 055d24df95 WORKING
2025-10-14 02:37:44 +00:00

460 lines
13 KiB
JavaScript

import defined from "../Core/defined.js";
import MetadataType from "./MetadataType.js";
import ShaderDestination from "../Renderer/ShaderDestination.js";
/**
* Update the shader with defines, structs, and functions to handle
* voxel properties and statistics
* @function
*
* @param {VoxelRenderResources} renderResources
* @param {VoxelPrimitive} primitive
*
* @private
*/
function processVoxelProperties(renderResources, primitive) {
const { shaderBuilder } = renderResources;
const {
names,
types,
componentTypes,
minimumValues,
maximumValues,
} = primitive._provider;
const attributeLength = types.length;
const hasStatistics = defined(minimumValues) && defined(maximumValues);
shaderBuilder.addDefine(
"METADATA_COUNT",
attributeLength,
ShaderDestination.FRAGMENT
);
if (hasStatistics) {
shaderBuilder.addDefine(
"STATISTICS",
undefined,
ShaderDestination.FRAGMENT
);
}
// PropertyStatistics structs
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const propertyStatisticsStructId = `PropertyStatistics_${name}`;
const propertyStatisticsStructName = `PropertyStatistics_${name}`;
shaderBuilder.addStruct(
propertyStatisticsStructId,
propertyStatisticsStructName,
ShaderDestination.FRAGMENT
);
const glslType = getGlslType(type);
shaderBuilder.addStructField(propertyStatisticsStructId, glslType, "min");
shaderBuilder.addStructField(propertyStatisticsStructId, glslType, "max");
}
// Statistics struct
const statisticsStructId = "Statistics";
const statisticsStructName = "Statistics";
const statisticsFieldName = "statistics";
shaderBuilder.addStruct(
statisticsStructId,
statisticsStructName,
ShaderDestination.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const propertyStructName = `PropertyStatistics_${name}`;
const propertyFieldName = name;
shaderBuilder.addStructField(
statisticsStructId,
propertyStructName,
propertyFieldName
);
}
// Metadata struct
const metadataStructId = "Metadata";
const metadataStructName = "Metadata";
const metadataFieldName = "metadata";
shaderBuilder.addStruct(
metadataStructId,
metadataStructName,
ShaderDestination.FRAGMENT
);
shaderBuilder.addStructField(
metadataStructId,
statisticsStructName,
statisticsFieldName
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const glslType = getGlslType(type);
shaderBuilder.addStructField(metadataStructId, glslType, name);
}
// VoxelProperty structs
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const glslType = getGlslPartialDerivativeType(type);
const voxelPropertyStructId = `VoxelProperty_${name}`;
const voxelPropertyStructName = `VoxelProperty_${name}`;
shaderBuilder.addStruct(
voxelPropertyStructId,
voxelPropertyStructName,
ShaderDestination.FRAGMENT
);
shaderBuilder.addStructField(
voxelPropertyStructId,
glslType,
"partialDerivativeLocal"
);
shaderBuilder.addStructField(
voxelPropertyStructId,
glslType,
"partialDerivativeWorld"
);
shaderBuilder.addStructField(
voxelPropertyStructId,
glslType,
"partialDerivativeView"
);
shaderBuilder.addStructField(
voxelPropertyStructId,
glslType,
"partialDerivativeValid"
);
}
// Voxel struct
const voxelStructId = "Voxel";
const voxelStructName = "Voxel";
const voxelFieldName = "voxel";
shaderBuilder.addStruct(
voxelStructId,
voxelStructName,
ShaderDestination.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const voxelPropertyStructName = `VoxelProperty_${name}`;
shaderBuilder.addStructField(voxelStructId, voxelPropertyStructName, name);
}
shaderBuilder.addStructField(voxelStructId, "vec3", "positionEC");
shaderBuilder.addStructField(voxelStructId, "vec3", "positionUv");
shaderBuilder.addStructField(voxelStructId, "vec3", "positionShapeUv");
shaderBuilder.addStructField(voxelStructId, "vec3", "positionUvLocal");
shaderBuilder.addStructField(voxelStructId, "vec3", "viewDirUv");
shaderBuilder.addStructField(voxelStructId, "vec3", "viewDirWorld");
shaderBuilder.addStructField(voxelStructId, "vec3", "surfaceNormal");
shaderBuilder.addStructField(voxelStructId, "float", "travelDistance");
shaderBuilder.addStructField(voxelStructId, "int", "stepCount");
shaderBuilder.addStructField(voxelStructId, "int", "tileIndex");
shaderBuilder.addStructField(voxelStructId, "int", "sampleIndex");
// FragmentInput struct
const fragmentInputStructId = "FragmentInput";
const fragmentInputStructName = "FragmentInput";
shaderBuilder.addStruct(
fragmentInputStructId,
fragmentInputStructName,
ShaderDestination.FRAGMENT
);
shaderBuilder.addStructField(
fragmentInputStructId,
metadataStructName,
metadataFieldName
);
shaderBuilder.addStructField(
fragmentInputStructId,
voxelStructName,
voxelFieldName
);
// Properties struct
const propertiesStructId = "Properties";
const propertiesStructName = "Properties";
const propertiesFieldName = "properties";
shaderBuilder.addStruct(
propertiesStructId,
propertiesStructName,
ShaderDestination.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const glslType = getGlslType(type);
shaderBuilder.addStructField(propertiesStructId, glslType, name);
}
// Fragment shader functions
// clearProperties function
{
const functionId = "clearProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} clearProperties()`,
ShaderDestination.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`,
]);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const componentType = componentTypes[i];
const glslType = getGlslType(type, componentType);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesFieldName}.${name} = ${glslType}(0.0);`,
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`,
]);
}
// sumProperties function
{
const functionId = "sumProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} sumProperties(${propertiesStructName} propertiesA, ${propertiesStructName} propertiesB)`,
ShaderDestination.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`,
]);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
shaderBuilder.addFunctionLines(functionId, [
`${propertiesFieldName}.${name} = propertiesA.${name} + propertiesB.${name};`,
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`,
]);
}
// scaleProperties function
{
const functionId = "scaleProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} scaleProperties(${propertiesStructName} ${propertiesFieldName}, float scale)`,
ShaderDestination.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} scaledProperties = ${propertiesFieldName};`,
]);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
shaderBuilder.addFunctionLines(functionId, [
`scaledProperties.${name} *= scale;`,
]);
}
shaderBuilder.addFunctionLines(functionId, [`return scaledProperties;`]);
}
// mixProperties
{
const functionId = "mixProperties";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} mixProperties(${propertiesStructName} propertiesA, ${propertiesStructName} propertiesB, float mixFactor)`,
ShaderDestination.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`,
]);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
shaderBuilder.addFunctionLines(functionId, [
`${propertiesFieldName}.${name} = mix(propertiesA.${name}, propertiesB.${name}, mixFactor);`,
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`,
]);
}
// copyPropertiesToMetadata
{
const functionId = "copyPropertiesToMetadata";
shaderBuilder.addFunction(
functionId,
`void copyPropertiesToMetadata(in ${propertiesStructName} ${propertiesFieldName}, inout ${metadataStructName} ${metadataFieldName})`,
ShaderDestination.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
shaderBuilder.addFunctionLines(functionId, [
`${metadataFieldName}.${name} = ${propertiesFieldName}.${name};`,
]);
}
}
// setStatistics function
if (hasStatistics) {
const functionId = "setStatistics";
shaderBuilder.addFunction(
functionId,
`void setStatistics(inout ${statisticsStructName} ${statisticsFieldName})`,
ShaderDestination.FRAGMENT
);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const componentCount = MetadataType.getComponentCount(type);
for (let j = 0; j < componentCount; j++) {
const glslField = getGlslField(type, j);
const minimumValue = minimumValues[i][j];
const maximumValue = maximumValues[i][j];
shaderBuilder.addFunctionLines(functionId, [
`${statisticsFieldName}.${name}.min${glslField} = ${getGlslNumberAsFloat(
minimumValue
)};`,
`${statisticsFieldName}.${name}.max${glslField} = ${getGlslNumberAsFloat(
maximumValue
)};`,
]);
}
}
}
// getPropertiesFromMegatextureAtUv
{
const functionId = "getPropertiesFromMegatextureAtUv";
shaderBuilder.addFunction(
functionId,
`${propertiesStructName} getPropertiesFromMegatextureAtUv(vec2 texcoord)`,
ShaderDestination.FRAGMENT
);
shaderBuilder.addFunctionLines(functionId, [
`${propertiesStructName} ${propertiesFieldName};`,
]);
for (let i = 0; i < attributeLength; i++) {
const name = names[i];
const type = types[i];
const componentType = componentTypes[i];
const glslTextureSwizzle = getGlslTextureSwizzle(type, componentType);
shaderBuilder.addFunctionLines(functionId, [
`properties.${name} = texture(u_megatextureTextures[${i}], texcoord)${glslTextureSwizzle};`,
]);
}
shaderBuilder.addFunctionLines(functionId, [
`return ${propertiesFieldName};`,
]);
}
}
/**
* Converts a {@link MetadataType} to a GLSL type.
*
* @function
*
* @param {MetadataType} type The {@link MetadataType}.
* @returns {string} The GLSL type.
*
* @private
*/
function getGlslType(type) {
if (type === MetadataType.SCALAR) {
return "float";
} else if (type === MetadataType.VEC2) {
return "vec2";
} else if (type === MetadataType.VEC3) {
return "vec3";
} else if (type === MetadataType.VEC4) {
return "vec4";
}
}
/**
* Gets the GLSL swizzle when reading data from a texture.
*
* @function
*
* @param {MetadataType} type The {@link MetadataType}.
* @returns {string} The GLSL swizzle.
*
* @private
*/
function getGlslTextureSwizzle(type) {
if (type === MetadataType.SCALAR) {
return ".r";
} else if (type === MetadataType.VEC2) {
return ".ra";
} else if (type === MetadataType.VEC3) {
return ".rgb";
} else if (type === MetadataType.VEC4) {
return "";
}
}
/**
* Gets the GLSL type of the partial derivative of {@link MetadataType}.
*
* @function
*
* @param {MetadataType} type The {@link MetadataType}.
* @returns {string} The GLSL type.
*
* @private
*/
function getGlslPartialDerivativeType(type) {
if (type === MetadataType.SCALAR) {
return "vec3";
} else if (type === MetadataType.VEC2) {
return "mat2";
} else if (type === MetadataType.VEC3) {
return "mat3";
} else if (type === MetadataType.VEC4) {
return "mat4";
}
}
/**
* GLSL needs to have `.0` at the end of whole number floats or else it's
* treated like an integer.
*
* @function
*
* @param {number} number The number to convert.
* @returns {string} The number as floating point in GLSL.
*
* @private
*/
function getGlslNumberAsFloat(number) {
let numberString = number.toString();
if (numberString.indexOf(".") === -1) {
numberString = `${number}.0`;
}
return numberString;
}
/**
* Gets the GLSL field
*
* @function
*
* @param {MetadataType} type
* @param {number} index
* @returns {string}
*
* @private
*/
function getGlslField(type, index) {
if (type === MetadataType.SCALAR) {
return "";
}
return `[${index}]`;
}
export default processVoxelProperties;