VoxelFS.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. //This file is automatically rebuilt by the Cesium build process.
  2. export default "// See Intersection.glsl for the definition of intersectScene\n\
  3. // See IntersectionUtils.glsl for the definition of nextIntersection\n\
  4. // See convertUvToBox.glsl, convertUvToCylinder.glsl, or convertUvToEllipsoid.glsl\n\
  5. // for the definition of convertUvToShapeUvSpace. The appropriate function is \n\
  6. // selected based on the VoxelPrimitive shape type, and added to the shader in\n\
  7. // Scene/VoxelRenderResources.js.\n\
  8. // See Octree.glsl for the definitions of TraversalData, SampleData,\n\
  9. // traverseOctreeFromBeginning, and traverseOctreeFromExisting\n\
  10. // See Megatexture.glsl for the definition of accumulatePropertiesFromMegatexture\n\
  11. \n\
  12. #define STEP_COUNT_MAX 1000 // Harcoded value because GLSL doesn't like variable length loops\n\
  13. #define ALPHA_ACCUM_MAX 0.98 // Must be > 0.0 and <= 1.0\n\
  14. \n\
  15. uniform mat3 u_transformDirectionViewToLocal;\n\
  16. uniform vec3 u_cameraPositionUv;\n\
  17. uniform float u_stepSize;\n\
  18. \n\
  19. #if defined(PICKING)\n\
  20. uniform vec4 u_pickColor;\n\
  21. #endif\n\
  22. \n\
  23. #if defined(JITTER)\n\
  24. float hash(vec2 p)\n\
  25. {\n\
  26. vec3 p3 = fract(vec3(p.xyx) * 50.0); // magic number = hashscale\n\
  27. p3 += dot(p3, p3.yzx + 19.19);\n\
  28. return fract((p3.x + p3.y) * p3.z);\n\
  29. }\n\
  30. #endif\n\
  31. \n\
  32. vec4 getStepSize(in SampleData sampleData, in Ray viewRay, in RayShapeIntersection shapeIntersection) {\n\
  33. #if defined(SHAPE_BOX)\n\
  34. Box voxelBox = constructVoxelBox(sampleData.tileCoords, sampleData.tileUv);\n\
  35. RayShapeIntersection voxelIntersection = intersectBox(viewRay, voxelBox);\n\
  36. vec4 entry = shapeIntersection.entry.w >= voxelIntersection.entry.w ? shapeIntersection.entry : voxelIntersection.entry;\n\
  37. float exit = min(voxelIntersection.exit.w, shapeIntersection.exit.w);\n\
  38. float dt = (exit - entry.w) * RAY_SCALE;\n\
  39. return vec4(normalize(entry.xyz), dt);\n\
  40. #else\n\
  41. float dimAtLevel = pow(2.0, float(sampleData.tileCoords.w));\n\
  42. return vec4(viewRay.dir, u_stepSize / dimAtLevel);\n\
  43. #endif\n\
  44. }\n\
  45. \n\
  46. void main()\n\
  47. {\n\
  48. vec4 fragCoord = gl_FragCoord;\n\
  49. vec2 screenCoord = (fragCoord.xy - czm_viewport.xy) / czm_viewport.zw; // [0,1]\n\
  50. vec3 eyeDirection = normalize(czm_windowToEyeCoordinates(fragCoord).xyz);\n\
  51. vec3 viewDirWorld = normalize(czm_inverseViewRotation * eyeDirection); // normalize again just in case\n\
  52. vec3 viewDirUv = normalize(u_transformDirectionViewToLocal * eyeDirection); // normalize again just in case\n\
  53. vec3 viewPosUv = u_cameraPositionUv;\n\
  54. #if defined(SHAPE_BOX)\n\
  55. vec3 dInv = 1.0 / viewDirUv;\n\
  56. Ray viewRayUv = Ray(viewPosUv, viewDirUv, dInv);\n\
  57. #else\n\
  58. Ray viewRayUv = Ray(viewPosUv, viewDirUv);\n\
  59. #endif\n\
  60. \n\
  61. Intersections ix;\n\
  62. RayShapeIntersection shapeIntersection = intersectScene(screenCoord, viewRayUv, ix);\n\
  63. \n\
  64. // Exit early if the scene was completely missed.\n\
  65. if (shapeIntersection.entry.w == NO_HIT) {\n\
  66. discard;\n\
  67. }\n\
  68. \n\
  69. float currT = shapeIntersection.entry.w * RAY_SCALE;\n\
  70. float endT = shapeIntersection.exit.w;\n\
  71. vec3 positionUv = viewPosUv + currT * viewDirUv;\n\
  72. vec3 positionUvShapeSpace = convertUvToShapeUvSpace(positionUv);\n\
  73. \n\
  74. // Traverse the tree from the start position\n\
  75. TraversalData traversalData;\n\
  76. SampleData sampleDatas[SAMPLE_COUNT];\n\
  77. traverseOctreeFromBeginning(positionUvShapeSpace, traversalData, sampleDatas);\n\
  78. vec4 step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection);\n\
  79. \n\
  80. #if defined(JITTER)\n\
  81. float noise = hash(screenCoord); // [0,1]\n\
  82. currT += noise * step.w;\n\
  83. positionUv += noise * step.w * viewDirUv;\n\
  84. #endif\n\
  85. \n\
  86. FragmentInput fragmentInput;\n\
  87. #if defined(STATISTICS)\n\
  88. setStatistics(fragmentInput.metadata.statistics);\n\
  89. #endif\n\
  90. \n\
  91. vec4 colorAccum =vec4(0.0);\n\
  92. \n\
  93. for (int stepCount = 0; stepCount < STEP_COUNT_MAX; ++stepCount) {\n\
  94. // Read properties from the megatexture based on the traversal state\n\
  95. Properties properties = accumulatePropertiesFromMegatexture(sampleDatas);\n\
  96. \n\
  97. // Prepare the custom shader inputs\n\
  98. copyPropertiesToMetadata(properties, fragmentInput.metadata);\n\
  99. fragmentInput.voxel.positionUv = positionUv;\n\
  100. fragmentInput.voxel.positionShapeUv = positionUvShapeSpace;\n\
  101. fragmentInput.voxel.positionUvLocal = sampleDatas[0].tileUv;\n\
  102. fragmentInput.voxel.viewDirUv = viewDirUv;\n\
  103. fragmentInput.voxel.viewDirWorld = viewDirWorld;\n\
  104. fragmentInput.voxel.surfaceNormal = step.xyz;\n\
  105. fragmentInput.voxel.travelDistance = step.w;\n\
  106. \n\
  107. // Run the custom shader\n\
  108. czm_modelMaterial materialOutput;\n\
  109. fragmentMain(fragmentInput, materialOutput);\n\
  110. \n\
  111. // Sanitize the custom shader output\n\
  112. vec4 color = vec4(materialOutput.diffuse, materialOutput.alpha);\n\
  113. color.rgb = max(color.rgb, vec3(0.0));\n\
  114. color.a = clamp(color.a, 0.0, 1.0);\n\
  115. \n\
  116. // Pre-multiplied alpha blend\n\
  117. colorAccum += (1.0 - colorAccum.a) * vec4(color.rgb * color.a, color.a);\n\
  118. \n\
  119. // Stop traversing if the alpha has been fully saturated\n\
  120. if (colorAccum.a > ALPHA_ACCUM_MAX) {\n\
  121. colorAccum.a = ALPHA_ACCUM_MAX;\n\
  122. break;\n\
  123. }\n\
  124. \n\
  125. if (step.w == 0.0) {\n\
  126. // Shape is infinitely thin. The ray may have hit the edge of a\n\
  127. // foreground voxel. Step ahead slightly to check for more voxels\n\
  128. step.w == 0.00001;\n\
  129. }\n\
  130. \n\
  131. // Keep raymarching\n\
  132. currT += step.w;\n\
  133. positionUv += step.w * viewDirUv;\n\
  134. \n\
  135. // Check if there's more intersections.\n\
  136. if (currT > endT) {\n\
  137. #if (INTERSECTION_COUNT == 1)\n\
  138. break;\n\
  139. #else\n\
  140. shapeIntersection = nextIntersection(ix);\n\
  141. if (shapeIntersection.entry.w == NO_HIT) {\n\
  142. break;\n\
  143. } else {\n\
  144. // Found another intersection. Resume raymarching there\n\
  145. currT = shapeIntersection.entry.w * RAY_SCALE;\n\
  146. endT = shapeIntersection.exit.w;\n\
  147. positionUv = viewPosUv + currT * viewDirUv;\n\
  148. }\n\
  149. #endif\n\
  150. }\n\
  151. \n\
  152. // Traverse the tree from the current ray position.\n\
  153. // This is similar to traverseOctreeFromBeginning but is faster when the ray is in the same tile as the previous step.\n\
  154. positionUvShapeSpace = convertUvToShapeUvSpace(positionUv);\n\
  155. traverseOctreeFromExisting(positionUvShapeSpace, traversalData, sampleDatas);\n\
  156. step = getStepSize(sampleDatas[0], viewRayUv, shapeIntersection);\n\
  157. }\n\
  158. \n\
  159. // Convert the alpha from [0,ALPHA_ACCUM_MAX] to [0,1]\n\
  160. colorAccum.a /= ALPHA_ACCUM_MAX;\n\
  161. \n\
  162. #if defined(PICKING)\n\
  163. // If alpha is 0.0 there is nothing to pick\n\
  164. if (colorAccum.a == 0.0) {\n\
  165. discard;\n\
  166. }\n\
  167. out_FragColor = u_pickColor;\n\
  168. #else\n\
  169. out_FragColor = colorAccum;\n\
  170. #endif\n\
  171. }\n\
  172. ";