| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- 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 glslType = getGlslType(types[i]);
- const propertyStatisticsStructId = `PropertyStatistics_${name}`;
- const propertyStatisticsStructName = `PropertyStatistics_${name}`;
- shaderBuilder.addStruct(
- propertyStatisticsStructId,
- propertyStatisticsStructName,
- ShaderDestination.FRAGMENT,
- );
- shaderBuilder.addStructField(propertyStatisticsStructId, glslType, "min");
- shaderBuilder.addStructField(propertyStatisticsStructId, glslType, "max");
- }
-
- // MetadataStatistics struct
- const metadataStatisticsStructId = "MetadataStatistics";
- const metadataStatisticsStructName = "MetadataStatistics";
- const metadataStatisticsFieldName = "metadataStatistics";
- shaderBuilder.addStruct(
- metadataStatisticsStructId,
- metadataStatisticsStructName,
- ShaderDestination.FRAGMENT,
- );
- for (let i = 0; i < attributeLength; i++) {
- const name = names[i];
- const propertyStructName = `PropertyStatistics_${name}`;
- const propertyFieldName = name;
- shaderBuilder.addStructField(
- metadataStatisticsStructId,
- propertyStructName,
- propertyFieldName,
- );
- }
-
- // Metadata struct
- const metadataStructId = "Metadata";
- const metadataStructName = "Metadata";
- const metadataFieldName = "metadata";
- shaderBuilder.addStruct(
- metadataStructId,
- metadataStructName,
- ShaderDestination.FRAGMENT,
- );
- for (let i = 0; i < attributeLength; i++) {
- const glslType = getGlslType(types[i]);
- shaderBuilder.addStructField(metadataStructId, glslType, names[i]);
- }
-
- // Attributes struct
- const attributesStructId = "Attributes";
- const attributesStructName = "Attributes";
- const attributesFieldName = "attributes";
- shaderBuilder.addStruct(
- attributesStructId,
- attributesStructName,
- ShaderDestination.FRAGMENT,
- );
- shaderBuilder.addStructField(attributesStructId, "vec3", "positionEC");
- shaderBuilder.addStructField(attributesStructId, "vec3", "normalEC");
-
- // Voxel struct
- const voxelStructId = "Voxel";
- const voxelStructName = "Voxel";
- const voxelFieldName = "voxel";
- shaderBuilder.addStruct(
- voxelStructId,
- voxelStructName,
- ShaderDestination.FRAGMENT,
- );
- shaderBuilder.addStructField(voxelStructId, "vec3", "viewDirUv");
- shaderBuilder.addStructField(voxelStructId, "float", "travelDistance");
- shaderBuilder.addStructField(voxelStructId, "int", "stepCount");
- shaderBuilder.addStructField(voxelStructId, "int", "tileIndex");
- shaderBuilder.addStructField(voxelStructId, "int", "sampleIndex");
- shaderBuilder.addStructField(voxelStructId, "float", "distanceToDepthBuffer");
-
- // FragmentInput struct
- const fragmentInputStructId = "FragmentInput";
- const fragmentInputStructName = "FragmentInput";
- shaderBuilder.addStruct(
- fragmentInputStructId,
- fragmentInputStructName,
- ShaderDestination.FRAGMENT,
- );
- shaderBuilder.addStructField(
- fragmentInputStructId,
- metadataStatisticsStructName,
- metadataStatisticsFieldName,
- );
- shaderBuilder.addStructField(
- fragmentInputStructId,
- metadataStructName,
- metadataFieldName,
- );
- shaderBuilder.addStructField(
- fragmentInputStructId,
- attributesStructName,
- attributesFieldName,
- );
- 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 glslType = getGlslType(types[i]);
- shaderBuilder.addStructField(propertiesStructId, glslType, names[i]);
- }
-
- // 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 glslType = getGlslType(types[i], componentTypes[i]);
- shaderBuilder.addFunctionLines(functionId, [
- `${propertiesFieldName}.${names[i]} = ${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++) {
- shaderBuilder.addFunctionLines(functionId, [
- `scaledProperties.${names[i]} *= 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 ${metadataStatisticsStructName} ${metadataStatisticsFieldName})`,
- 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];
- if (!defined(minimumValue) || !defined(maximumValue)) {
- continue;
- }
- shaderBuilder.addFunctionLines(functionId, [
- `${metadataStatisticsFieldName}.${name}.min${glslField} = ${getGlslNumberAsFloat(
- minimumValue,
- )};`,
- `${metadataStatisticsFieldName}.${name}.max${glslField} = ${getGlslNumberAsFloat(
- maximumValue,
- )};`,
- ]);
- }
- }
- }
-
- // getPropertiesFromMegatextureAtUv
- {
- const functionId = "getPropertiesFromMegatextureAtUv";
- shaderBuilder.addFunction(
- functionId,
- `${propertiesStructName} getPropertiesFromMegatextureAtUv(vec3 texcoord)`,
- ShaderDestination.FRAGMENT,
- );
- shaderBuilder.addFunctionLines(functionId, [
- `${propertiesStructName} ${propertiesFieldName};`,
- ]);
- for (let i = 0; i < attributeLength; i++) {
- const type = types[i];
- const componentType = componentTypes[i];
- const glslTextureSwizzle = getGlslTextureSwizzle(type, componentType);
- shaderBuilder.addFunctionLines(functionId, [
- `properties.${names[i]} = 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 "";
- }
- }
-
- /**
- * 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;
|