All files / engine/Source/Shaders/Voxels Megatexture.js

0% Statements 0/0
0% Branches 0/0
0% Functions 0/0
0% Lines 0/0

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126                                                                                                                                                                                                                                                           
//This file is automatically rebuilt by the Cesium build process.
export default "// See Octree.glsl for the definitions of SampleData and intMod\n\
\n\
/* Megatexture defines (set in Scene/VoxelRenderResources.js)\n\
#define SAMPLE_COUNT ###\n\
#define NEAREST_SAMPLING\n\
#define PADDING\n\
*/\n\
\n\
uniform ivec2 u_megatextureSliceDimensions; // number of slices per tile, in two dimensions\n\
uniform ivec2 u_megatextureTileDimensions; // number of tiles per megatexture, in two dimensions\n\
uniform vec2 u_megatextureVoxelSizeUv;\n\
uniform vec2 u_megatextureSliceSizeUv;\n\
uniform vec2 u_megatextureTileSizeUv;\n\
\n\
// Integer min, max, clamp: For WebGL1 only\n\
int intMin(int a, int b) {\n\
    return a <= b ? a : b;\n\
}\n\
int intMax(int a, int b) {\n\
    return a >= b ? a : b;\n\
}\n\
int intClamp(int v, int minVal, int maxVal) {\n\
    return intMin(intMax(v, minVal), maxVal);\n\
}\n\
\n\
vec2 index1DTo2DTexcoord(int index, ivec2 dimensions, vec2 uvScale)\n\
{\n\
    int indexX = intMod(index, dimensions.x);\n\
    int indexY = index / dimensions.x;\n\
    return vec2(indexX, indexY) * uvScale;\n\
}\n\
\n\
/*\n\
    How is 3D data stored in a 2D megatexture?\n\
\n\
    In this example there is only one loaded tile and it has 2x2x2 voxels (8 voxels total).\n\
    The data is sliced by Z. The data at Z = 0 is placed in texels (0,0), (0,1), (1,0), (1,1) and\n\
    the data at Z = 1 is placed in texels (2,0), (2,1), (3,0), (3,1).\n\
    Note that there could be empty space in the megatexture because it's a power of two.\n\
\n\
      0   1   2   3\n\
    +---+---+---+---+\n\
    |   |   |   |   | 3\n\
    +---+---+---+---+\n\
    |   |   |   |   | 2\n\
    +-------+-------+\n\
    |010|110|011|111| 1\n\
    |--- ---|--- ---|\n\
    |000|100|001|101| 0\n\
    +-------+-------+\n\
\n\
    When doing linear interpolation the megatexture needs to be sampled twice: once for\n\
    the Z slice above the voxel coordinate and once for the slice below. The two slices\n\
    are interpolated with fract(coord.z - 0.5). For example, a Z coordinate of 1.0 is\n\
    halfway between two Z slices so the interpolation factor is 0.5. Below is a side view\n\
    of the 3D voxel grid with voxel coordinates on the left side.\n\
\n\
    2 +---+\n\
      |001|\n\
    1 +-z-+\n\
      |000|\n\
    0 +---+\n\
\n\
    When doing nearest neighbor the megatexture only needs to be sampled once at the closest Z slice.\n\
*/\n\
\n\
Properties getPropertiesFromMegatexture(in SampleData sampleData) {\n\
    int tileIndex = sampleData.megatextureIndex;\n\
\n\
    vec3 voxelCoord = sampleData.inputCoordinate;\n\
    #if defined(NEAREST_SAMPLING)\n\
        // Round to the center of the nearest voxel\n\
        voxelCoord = floor(voxelCoord) + vec3(0.5);\n\
    #endif\n\
\n\
    // Tile location\n\
    vec2 tileUvOffset = index1DTo2DTexcoord(tileIndex, u_megatextureTileDimensions, u_megatextureTileSizeUv);\n\
\n\
    // Slice location\n\
    float slice = voxelCoord.z - 0.5;\n\
    int sliceIndex = int(floor(slice));\n\
    int sliceIndex0 = intClamp(sliceIndex, 0, u_inputDimensions.z - 1);\n\
    vec2 sliceUvOffset0 = index1DTo2DTexcoord(sliceIndex0, u_megatextureSliceDimensions, u_megatextureSliceSizeUv);\n\
\n\
    // Voxel location\n\
    vec2 voxelUvOffset = clamp(voxelCoord.xy, vec2(0.5), vec2(u_inputDimensions.xy) - vec2(0.5)) * u_megatextureVoxelSizeUv;\n\
\n\
    // Final location in the megatexture\n\
    vec2 uv0 = tileUvOffset + sliceUvOffset0 + voxelUvOffset;\n\
\n\
    #if defined(NEAREST_SAMPLING)\n\
        return getPropertiesFromMegatextureAtUv(uv0);\n\
    #else\n\
        float sliceLerp = fract(slice);\n\
        int sliceIndex1 = intMin(sliceIndex + 1, u_inputDimensions.z - 1);\n\
        vec2 sliceUvOffset1 = index1DTo2DTexcoord(sliceIndex1, u_megatextureSliceDimensions, u_megatextureSliceSizeUv);\n\
        vec2 uv1 = tileUvOffset + sliceUvOffset1 + voxelUvOffset;\n\
        Properties properties0 = getPropertiesFromMegatextureAtUv(uv0);\n\
        Properties properties1 = getPropertiesFromMegatextureAtUv(uv1);\n\
        return mixProperties(properties0, properties1, sliceLerp);\n\
    #endif\n\
}\n\
\n\
// Convert an array of sample datas to a final weighted properties.\n\
Properties accumulatePropertiesFromMegatexture(in SampleData sampleDatas[SAMPLE_COUNT]) {\n\
    #if (SAMPLE_COUNT == 1)\n\
        return getPropertiesFromMegatexture(sampleDatas[0]);\n\
    #else\n\
        // When more than one sample is taken the accumulator needs to start at 0\n\
        Properties properties = clearProperties();\n\
        for (int i = 0; i < SAMPLE_COUNT; ++i) {\n\
            float weight = sampleDatas[i].weight;\n\
\n\
            // Avoid reading the megatexture when the weight is 0 as it can be costly.\n\
            if (weight > 0.0) {\n\
                Properties tempProperties = getPropertiesFromMegatexture(sampleDatas[i]);\n\
                tempProperties = scaleProperties(tempProperties, weight);\n\
                properties = sumProperties(properties, tempProperties);\n\
            }\n\
        }\n\
        return properties;\n\
    #endif\n\
}\n\
";