3131
3232; ; Volumetric clouds are commonly used in flight simulators and visual effects.
3333; ; For a introductory video see [Sebastian Lague's video "Coding Adventure: Clouds](https://www.youtube.com/watch?v=4QOcCGI6xOU).
34- ; ; Note that this article is about procedural generation and not about simulating real weather .
34+ ; ; This article gets you started with computing and rendering volumetric clouds .
3535; ;
3636; ; ## Worley noise
3737; ;
8888
8989
9090; ; We can now use the `random-point` method to generate a grid of random points.
91+ ; ; The grid is represented using a tensor from the [dtype-next](https://cnuernber.github.io/dtype-next/) library.
9192(defn random-points
9293 [{:keys [divisions dimensions] :as params}]
9394 (tensor/clone
@@ -1081,7 +1082,12 @@ void main()
10811082 fragColor = vec4(background * (1.0 - transfer.a) + transfer.rgb, 1.0);
10821083}" )
10831084
1084-
1085+ ; ; Uniform variables are parameters that remain constant throughout the shader execution, unlike vertex input data.
1086+ ; ; Here we use the following uniform variables:
1087+ ; ; * resolution: a 2D vector containing the window pixel width and height
1088+ ; ; * light: a 3D unit vector pointing to the light source
1089+ ; ; * rotation: a 3x3 rotation matrix to rotate the camera around the origin
1090+ ; ; * focal_length: the ratio of camera focal length to pixel size of the virtual camera
10851091(defn setup-fog-uniforms
10861092 [program width height]
10871093 (let [rotation (mulm (rotation-matrix-3d-y (to-radians 40.0 ))
@@ -1097,7 +1103,8 @@ void main()
10971103 (GL20/glUniform1f (GL20/glGetUniformLocation program " focal_length" ) focal-length)
10981104 (GL20/glUniform1f (GL20/glGetUniformLocation program " distance" ) 2.0 )))
10991105
1100-
1106+ ; ; The following function sets up the shader program, the vertex array object, and the uniform variables.
1107+ ; ; Then `GL11/glDrawElements` draws the background quad used for performing volumetric rendering.
11011108(defn render-fog
11021109 [width height]
11031110 (let [fragment-sources [ray-box constant-scatter no-shadow (cloud-transfer " fog" 0.01 )
@@ -1113,15 +1120,21 @@ void main()
11131120 (teardown-vao vao)
11141121 (GL20/glDeleteProgram program)))))
11151122
1116-
1123+ ; ; We also need to convert the floating point array to a tensor and then to a `BufferedImage`.
1124+ ; ; The one-dimensional array gets converted to a tensor and then reshaped to a 3D tensor containing width × height RGBA values.
1125+ ; ; The RGBA data is converted to BGR data and then multiplied with 255 and clamped.
1126+ ; ; Finally the tensor is converted to a `BufferedImage`.
11171127(defn rgba-array->bufimg [data width height]
11181128 (-> data
11191129 tensor/->tensor
11201130 (tensor/reshape [height width 4 ])
1121- (tensor/select :all :all [2 1 0 ]) (dfn/* 255 ) (clamp 0 255 )))
1122-
1131+ (tensor/select :all :all [2 1 0 ])
1132+ (dfn/* 255 )
1133+ (clamp 0 255 )
1134+ bufimg/tensor->image))
11231135
1124- (bufimg/tensor->image (rgba-array->bufimg (render-fog 640 480 ) 640 480 ))
1136+ ; ; Finally we are ready to render the volumetric fog.
1137+ (rgba-array->bufimg (render-fog 640 480 ) 640 480 )
11251138
11261139
11271140; ; ### Rendering of 3D noise
@@ -1180,11 +1193,10 @@ float noise(vec3 idx)
11801193 (GL20/glDeleteProgram program)))))
11811194
11821195
1183- (bufimg/tensor->image
1184- (rgba-array->bufimg
1185- (render-noise 640 480
1186- constant-scatter no-shadow (cloud-transfer " noise" 0.01 ) noise-shader)
1187- 640 480 ))
1196+ (rgba-array->bufimg
1197+ (render-noise 640 480
1198+ constant-scatter no-shadow (cloud-transfer " noise" 0.01 ) noise-shader)
1199+ 640 480 )
11881200
11891201
11901202; ; ### Remap and clamp 3D noise
@@ -1240,22 +1252,20 @@ float remap_noise(vec3 idx)
12401252(def cloud-strength 6.5 )
12411253
12421254
1243- (bufimg/tensor->image
1244- (rgba-array->bufimg
1245- (render-noise 640 480
1246- constant-scatter no-shadow (cloud-transfer " remap_noise" 0.01 )
1247- remap-clamp (remap-noise " noise" 0.45 0.9 cloud-strength) noise-shader)
1248- 640 480 ))
1255+ (rgba-array->bufimg
1256+ (render-noise 640 480
1257+ constant-scatter no-shadow (cloud-transfer " remap_noise" 0.01 )
1258+ remap-clamp (remap-noise " noise" 0.45 0.9 cloud-strength) noise-shader)
1259+ 640 480 )
12491260
12501261
12511262; ; ### Octaves of 3D noise
12521263
1253- (bufimg/tensor->image
1254- (rgba-array->bufimg
1255- (render-noise 640 480 constant-scatter no-shadow (cloud-transfer " remap_noise" 0.01 )
1256- remap-clamp (remap-noise " octaves" 0.45 0.9 cloud-strength)
1257- (noise-octaves (octaves 4 0.5 )) noise-shader)
1258- 640 480 ))
1264+ (rgba-array->bufimg
1265+ (render-noise 640 480 constant-scatter no-shadow (cloud-transfer " remap_noise" 0.01 )
1266+ remap-clamp (remap-noise " octaves" 0.45 0.9 cloud-strength)
1267+ (noise-octaves (octaves 4 0.5 )) noise-shader)
1268+ 640 480 )
12591269
12601270
12611271; ; ### Mie scattering
@@ -1320,12 +1330,11 @@ void main()
13201330 (assoc-in [:layout :yaxis :scaleanchor ] " x" )))
13211331
13221332
1323- (bufimg/tensor->image
1324- (rgba-array->bufimg
1325- (render-noise 640 480 (mie-scatter 0.76 ) no-shadow (cloud-transfer " remap_noise" 0.01 )
1326- remap-clamp (remap-noise " octaves" 0.45 0.9 cloud-strength)
1327- (noise-octaves (octaves 4 0.5 )) noise-shader)
1328- 640 480 ))
1333+ (rgba-array->bufimg
1334+ (render-noise 640 480 (mie-scatter 0.76 ) no-shadow (cloud-transfer " remap_noise" 0.01 )
1335+ remap-clamp (remap-noise " octaves" 0.45 0.9 cloud-strength)
1336+ (noise-octaves (octaves 4 0.5 )) noise-shader)
1337+ 640 480 )
13291338
13301339
13311340; ; ### Self-shading of clouds
@@ -1349,14 +1358,13 @@ float shadow(vec3 point)
13491358}" ))
13501359
13511360
1352- (bufimg/tensor->image
1353- (rgba-array->bufimg
1354- (render-noise 640 480
1355- (mie-scatter 0.76 ) (shadow " remap_noise" 0.01 )
1356- (cloud-transfer " remap_noise" 0.01 ) remap-clamp
1357- (remap-noise " octaves" 0.45 0.9 cloud-strength)
1358- (noise-octaves (octaves 4 0.5 )) noise-shader)
1359- 640 480 ))
1361+ (rgba-array->bufimg
1362+ (render-noise 640 480
1363+ (mie-scatter 0.76 ) (shadow " remap_noise" 0.01 )
1364+ (cloud-transfer " remap_noise" 0.01 ) remap-clamp
1365+ (remap-noise " octaves" 0.45 0.9 cloud-strength)
1366+ (noise-octaves (octaves 4 0.5 )) noise-shader)
1367+ 640 480 )
13601368
13611369; ; ### Tidy up
13621370(GL11/glBindTexture GL12/GL_TEXTURE_3D 0 )
0 commit comments