Skip to content

Commit 1b0a92c

Browse files
committed
Show octaves of 3D noise
1 parent f7f8a13 commit 1b0a92c

1 file changed

Lines changed: 92 additions & 19 deletions

File tree

src/volumetric_clouds/main.clj

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,10 @@
205205

206206
;; # Perlin noise
207207

208-
(defn random-gradient
208+
209+
(defmulti random-gradient (fn [& args] (count args)))
210+
211+
(defmethod random-gradient 2
209212
[& args]
210213
(loop [args args]
211214
(let [random-vector (apply vec-n (map (fn [_x] (- (rand 2.0) 1.0)) args))
@@ -215,6 +218,14 @@
215218
(recur args)))))
216219

217220

221+
(defmethod random-gradient 3
222+
[& _args]
223+
(apply vec3
224+
(rand-nth [[1 1 0] [-1 1 0] [1 -1 0] [-1 -1 0]
225+
[1 0 1] [-1 0 1] [1 0 -1] [-1 0 -1]
226+
[0 1 1] [ 0 -1 1] [0 1 -1] [ 0 -1 -1]])))
227+
228+
218229
(defn roughly-vec
219230
[expected error]
220231
(fn [actual]
@@ -234,11 +245,12 @@
234245

235246

236247
(facts "Random gradients"
237-
(with-redefs [rand (constantly 1.5)]
248+
(with-redefs [rand (constantly 1.5)
249+
rand-nth (fn [x] (first x))]
238250
(dtype/shape (random-gradients {:divisions 8 :dimensions 2})) => [8 8]
239251
((random-gradients {:divisions 8 :dimensions 2}) 0 0) => (roughly-vec (vec2 (sqrt 0.5) (sqrt 0.5)) 1e-6)
240252
(dtype/shape (random-gradients {:divisions 8 :dimensions 3})) => [8 8 8]
241-
((random-gradients {:divisions 8 :dimensions 3}) 0 0 0) => (roughly-vec (vec3 (sqrt (/ 1 3)) (sqrt (/ 1 3)) (sqrt (/ 1 3))) 1e-6)))
253+
((random-gradients {:divisions 8 :dimensions 3}) 0 0 0) => (vec3 1 1 0)))
242254

243255

244256
(let [gradients (tensor/reshape (random-gradients (make-noise-params 256 8 2)) [(* 8 8)])
@@ -489,6 +501,9 @@
489501
(mapv #(/ % sum) series)))
490502

491503

504+
(octaves 4 0.5)
505+
506+
492507
(defn noise-octaves
493508
[tensor octaves low high]
494509
(tensor/clone
@@ -810,30 +825,31 @@ void main()
810825

811826
;; # Shader for light transfer through clouds
812827

813-
(def cloud-mock
828+
(def fog
814829
(template/fn [v]
815830
"#version 130
816-
float cloud(vec3 idx)
831+
float fog(vec3 idx)
817832
{
818833
return <%= v %>;
819834
}"))
820835

821836

822837
(def cloud-transfer
838+
(template/fn [noise]
823839
"#version 130
824-
float cloud(vec3 idx);
840+
float <%= noise %>(vec3 idx);
825841
vec4 cloud_transfer(vec3 origin, vec3 direction, vec2 interval, float step)
826842
{
827843
vec4 result = vec4(0, 0, 0, 0);
828844
for (float t = interval.x + 0.5 * step; t < interval.y; t += step) {
829-
float density = cloud(origin + direction * t);
845+
float density = <%= noise %>(origin + direction * t);
830846
float transmittance = exp(-density * step);
831847
vec3 color = vec3(1.0, 1.0, 1.0);
832848
result.rgb = result.rgb + color * (1.0 - result.a) * (1.0 - transmittance);
833849
result.a = 1.0 - (1.0 - result.a) * transmittance;
834850
};
835851
return result;
836-
}")
852+
}"))
837853

838854

839855
(def cloud-transfer-probe
@@ -859,7 +875,7 @@ void main()
859875

860876

861877
(tabular "Test cloud transfer"
862-
(fact (seq (render-pixel [vertex-test] [(cloud-mock ?density) cloud-transfer (cloud-transfer-probe ?a ?b ?step)]))
878+
(fact (seq (render-pixel [vertex-test] [(fog ?density) (cloud-transfer "fog") (cloud-transfer-probe ?a ?b ?step)]))
863879
=> (roughly-vector ?result 1e-3))
864880
?a ?b ?step ?density ?result
865881
0 0 1 0.0 [0.0 0.0 0.0 0.0]
@@ -883,28 +899,28 @@ void main()
883899
{
884900
vec3 direction = normalize(rotation * vec3(gl_FragCoord.xy - 0.5 * resolution, focal_length));
885901
vec3 origin = rotation * vec3(0, 0, -distance);
886-
vec2 interval = ray_box(vec3(-1, -1, -1), vec3(1, 1, 1), origin, direction);
902+
vec2 interval = ray_box(vec3(-0.5, -0.5, -0.5), vec3(0.5, 0.5, 0.5), origin, direction);
887903
vec4 transfer = cloud_transfer(origin, direction, interval, 0.01);
888-
vec3 background = vec3(0.5, 0.5, 1.0);
904+
vec3 background = vec3(0.125, 0.125, 0.25);
889905
fragColor = vec4(background * (1.0 - transfer.a) + transfer.rgb, 1.0);
890906
}")
891907

892908

893909
(defn setup-fog-uniforms
894910
[program width height]
895-
(let [rotation (mulm (rotation-matrix-3d-y (to-radians 30.0)) (rotation-matrix-3d-x (to-radians -25.0)))
896-
focal-length (/ (* 0.5 width) (tan (to-radians 30.0)))]
911+
(let [rotation (mulm (rotation-matrix-3d-y (to-radians 30.0)) (rotation-matrix-3d-x (to-radians -20.0)))
912+
focal-length (/ (* 0.5 width) (tan (to-radians 25.0)))]
897913
(GL20/glUseProgram program)
898914
(GL20/glUniform2f (GL20/glGetUniformLocation program "resolution") width height)
899915
(GL20/glUniformMatrix3fv (GL20/glGetUniformLocation program "rotation") true
900916
(make-float-buffer (mat->float-array rotation)))
901917
(GL20/glUniform1f (GL20/glGetUniformLocation program "focal_length") focal-length)
902-
(GL20/glUniform1f (GL20/glGetUniformLocation program "distance") 4.0)))
918+
(GL20/glUniform1f (GL20/glGetUniformLocation program "distance") 2.5)))
903919

904920

905921
(defn render-fog
906922
[width height]
907-
(let [fragment-sources [ray-box cloud-transfer (cloud-mock 0.5) fragment-cloud]
923+
(let [fragment-sources [ray-box (cloud-transfer "fog") (fog 1.0) fragment-cloud]
908924
program (make-program-with-shaders [vertex-test] fragment-sources)
909925
vao (setup-quad-vao)
910926
texture (make-texture-2d width height)]
@@ -951,7 +967,7 @@ void main()
951967
(def noise-shader
952968
"#version 130
953969
uniform sampler3D noise3d;
954-
float cloud(vec3 idx)
970+
float noise(vec3 idx)
955971
{
956972
return texture(noise3d, idx).r;
957973
}")
@@ -966,8 +982,8 @@ float cloud(vec3 idx)
966982

967983

968984
(defn render-noise
969-
[width height]
970-
(let [fragment-sources [ray-box cloud-transfer noise-shader fragment-cloud]
985+
[width height & cloud-shaders]
986+
(let [fragment-sources (concat cloud-shaders [ray-box fragment-cloud])
971987
program (make-program-with-shaders [vertex-test] fragment-sources)
972988
vao (setup-quad-vao)
973989
texture (make-texture-2d width height)]
@@ -982,7 +998,64 @@ float cloud(vec3 idx)
982998
result)))
983999

9841000

985-
(bufimg/tensor->image (rgba-array->bufimg (render-noise 640 480) 640 480))
1001+
(bufimg/tensor->image (rgba-array->bufimg (render-noise 640 480 (cloud-transfer "noise") noise-shader) 640 480))
1002+
1003+
1004+
;; # Remap and clamp 3D noise
1005+
1006+
(def remap-clamp
1007+
"#version 130
1008+
float remap_clamp(float value, float low1, float high1, float low2, float high2)
1009+
{
1010+
float t = (value - low1) / (high1 - low1);
1011+
return clamp(low2 + t * (high2 - low2), low2, high2);
1012+
}")
1013+
1014+
1015+
(def remap-probe
1016+
(template/fn [value low1 high1 low2 high2]
1017+
"#version 130
1018+
out vec4 fragColor;
1019+
float remap_clamp(float value, float low1, float high1, float low2, float high2);
1020+
void main()
1021+
{
1022+
fragColor = vec4(remap_clamp(<%= value %>, <%= low1 %>, <%= high1 %>, <%= low2 %>, <%= high2 %>));
1023+
}"))
1024+
1025+
1026+
(tabular "Remap and clamp input parameter values"
1027+
(fact (first (render-pixel [vertex-test] [remap-clamp (remap-probe ?value ?low1 ?high1 ?low2 ?high2)]))
1028+
=> ?expected)
1029+
?value ?low1 ?high1 ?low2 ?high2 ?expected
1030+
0 0 1 0 1 0.0
1031+
1 0 1 0 1 1.0
1032+
0 0 1 2 3 2.0
1033+
1 0 1 2 3 3.0
1034+
2 2 3 0 1 0.0
1035+
3 2 3 0 1 1.0
1036+
1 0 2 0 4 2.0
1037+
0 1 2 1 2 1.0
1038+
3 1 2 1 2 2.0)
1039+
1040+
1041+
(def remap-noise
1042+
(template/fn [base low1 high1 high2]
1043+
"#version 130
1044+
float <%= base %>(vec3 idx);
1045+
float remap_clamp(float value, float low1, float high1, float low2, float high2);
1046+
float remap_noise(vec3 idx)
1047+
{
1048+
return remap_clamp(<%= base %>(idx), <%= low1 %>, <%= high1 %>, 0.0, <%= high2 %>);
1049+
}"))
1050+
1051+
1052+
(bufimg/tensor->image (rgba-array->bufimg (render-noise 640 480 (cloud-transfer "remap_noise") remap-clamp (remap-noise "noise" 0.45 0.9 1.5) noise-shader) 640 480))
1053+
1054+
1055+
;; # Octaves of 3D noise
1056+
1057+
(bufimg/tensor->image (rgba-array->bufimg (render-noise 640 480 (cloud-transfer "remap_noise") remap-clamp (remap-noise "octaves" 0.45 0.9 1.5) (noise-octaves (octaves 4 0.5)) noise-shader) 640 480))
1058+
9861059

9871060
(GL11/glDeleteTextures noise-texture)
9881061

0 commit comments

Comments
 (0)