Skip to content

Commit beba295

Browse files
committed
Got transparent box working
1 parent 2c8aece commit beba295

1 file changed

Lines changed: 113 additions & 14 deletions

File tree

src/volumetric_clouds/main.clj

Lines changed: 113 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010
:tags [:visualization]}}}
1111

1212
(ns volumetric-clouds.main
13-
(:require [clojure.math :refer (sqrt)]
13+
(:require [clojure.math :refer (sqrt tan to-radians)]
1414
[midje.sweet :refer (fact facts tabular => roughly)]
1515
[fastmath.vector :refer (vec2 vec3 add mult sub div mag dot)]
16+
[fastmath.matrix :refer (mat->float-array mulm rotation-matrix-3d-x rotation-matrix-3d-y)]
1617
[tech.v3.datatype :as dtype]
1718
[tech.v3.tensor :as tensor]
1819
[tech.v3.datatype.functional :as dfn]
@@ -639,29 +640,27 @@ void main()
639640
(GL20/glEnableVertexAttribArray point-attribute)))
640641

641642

642-
(defn render-pixels
643-
[vertex-sources fragment-sources width height]
643+
(defn render-pixel
644+
[vertex-sources fragment-sources]
644645
(let [vertices (float-array [1.0 1.0 0.0, -1.0 1.0 0.0, -1.0 -1.0 0.0, 1.0 -1.0 0.0])
645646
indices (int-array [0 1 2 3])
646-
vertex-shader (map #(make-shader % GL20/GL_VERTEX_SHADER) vertex-sources)
647+
vertex-shaders (map #(make-shader % GL20/GL_VERTEX_SHADER) vertex-sources)
647648
fragment-shaders (map #(make-shader % GL20/GL_FRAGMENT_SHADER) fragment-sources)
648-
program (apply make-program (concat vertex-shader fragment-shaders))
649+
program (apply make-program (concat vertex-shaders fragment-shaders))
649650
vao (setup-vao vertices indices)
650-
texture (make-texture width height)]
651+
texture (make-texture 1 1)]
651652
(setup-point-attribute program)
652-
(framebuffer-render texture width height
653+
(framebuffer-render texture 1 1
653654
(GL20/glUseProgram program)
654-
(GL11/glClearColor 1.0 0.5 0.25 1.0)
655-
(GL11/glClear GL11/GL_COLOR_BUFFER_BIT)
656655
(GL11/glDrawElements GL11/GL_QUADS (count indices) GL11/GL_UNSIGNED_INT 0))
657-
(let [result (read-texture texture width height)]
656+
(let [result (read-texture texture 1 1)]
658657
(GL11/glDeleteTextures texture)
659658
(teardown-vao vao)
660659
(GL20/glDeleteProgram program)
661660
result)))
662661

663662

664-
(render-pixels [vertex-test] [fragment-test] 1 1)
663+
(render-pixel [vertex-test] [fragment-test])
665664

666665

667666
(def noise-mock
@@ -685,7 +684,7 @@ void main()
685684

686685

687686
(tabular "Test noise mock"
688-
(fact (nth (render-pixels [vertex-test] [noise-mock (noise-probe ?x ?y ?z)] 1 1) 0) => ?result)
687+
(fact (nth (render-pixel [vertex-test] [noise-mock (noise-probe ?x ?y ?z)]) 0) => ?result)
689688
?x ?y ?z ?result
690689
0 0 0 0.0
691690
1 0 0 1.0
@@ -725,7 +724,7 @@ void main()
725724

726725

727726
(tabular "Test octaves of noise"
728-
(fact (nth (render-pixels [vertex-test] [noise-mock (noise-octaves ?octaves) (octaves-probe ?x ?y ?z)] 1 1) 0)
727+
(fact (first (render-pixel [vertex-test] [noise-mock (noise-octaves ?octaves) (octaves-probe ?x ?y ?z)]))
729728
=> ?result)
730729
?x ?y ?z ?octaves ?result
731730
0 0 0 [1.0] 0.0
@@ -770,7 +769,7 @@ void main()
770769

771770

772771
(tabular "Test intersection of ray with box"
773-
(fact ((juxt first second) (render-pixels [vertex-test] [ray-box (ray-box-probe ?ox ?oy ?oz ?dx ?dy ?dz)] 1 1))
772+
(fact ((juxt first second) (render-pixel [vertex-test] [ray-box (ray-box-probe ?ox ?oy ?oz ?dx ?dy ?dz)]))
774773
=> ?result)
775774
?ox ?oy ?oz ?dx ?dy ?dz ?result
776775
-2 0 0 1 0 0 [1.0 3.0]
@@ -795,6 +794,106 @@ float cloud(vec3 idx)
795794
}"))
796795

797796

797+
(def cloud-transfer
798+
"#version 130
799+
float cloud(vec3 idx);
800+
vec4 cloud_transfer(vec3 origin, vec3 direction, vec2 interval, float step)
801+
{
802+
vec4 result = vec4(0, 0, 0, 0);
803+
for (float t = interval.x + 0.5 * step; t < interval.y; t += step) {
804+
float density = cloud(origin + direction * t);
805+
float transmittance = exp(-density * step);
806+
vec3 color = vec3(1.0, 1.0, 1.0);
807+
result.rgb = result.rgb + color * (1.0 - result.a) * (1.0 - transmittance);
808+
result.a = 1.0 - (1.0 - result.a) * transmittance;
809+
};
810+
return result;
811+
}")
812+
813+
814+
(def cloud-transfer-probe
815+
(template/fn [a b step]
816+
"#version 130
817+
out vec4 fragColor;
818+
vec4 cloud_transfer(vec3 origin, vec3 direction, vec2 interval, float step);
819+
void main()
820+
{
821+
vec3 origin = vec3(0, 0, 0);
822+
vec3 direction = vec3(1, 0, 0);
823+
vec2 interval = vec2(<%= a %>, <%= b %>);
824+
float step = <%= step %>;
825+
fragColor = cloud_transfer(origin, direction, interval, step);
826+
}"))
827+
828+
829+
(defn roughly-vector
830+
[expected error]
831+
(fn [actual]
832+
(and (== (count expected) (count actual))
833+
(<= (apply + (mapv (fn [a b] (* (- b a) (- b a))) actual expected)) (* error error)))))
834+
835+
836+
(tabular "Test cloud transfer"
837+
(fact (seq (render-pixel [vertex-test] [(cloud-mock ?density) cloud-transfer (cloud-transfer-probe ?a ?b ?step)]))
838+
=> (roughly-vector ?result 1e-3))
839+
?a ?b ?step ?density ?result
840+
0 0 1 0.0 [0.0 0.0 0.0 0.0]
841+
0 1 1 1.0 [0.632 0.632 0.632 0.632]
842+
0 1 0.5 1.0 [0.632 0.632 0.632 0.632]
843+
0 1 0.5 0.5 [0.393 0.393 0.393 0.393])
844+
845+
846+
(def fragment-cloud
847+
"#version 130
848+
uniform vec2 resolution;
849+
uniform mat3 rotation;
850+
uniform float focal_length;
851+
uniform float distance;
852+
out vec4 fragColor;
853+
vec2 ray_box(vec3 box_min, vec3 box_max, vec3 origin, vec3 direction);
854+
vec4 cloud_transfer(vec3 origin, vec3 direction, vec2 interval, float step);
855+
void main()
856+
{
857+
vec3 direction = normalize(rotation * vec3(gl_FragCoord.xy - 0.5 * resolution, focal_length));
858+
vec3 origin = rotation * vec3(0, 0, -distance);
859+
vec2 interval = ray_box(vec3(-1, -1, -1), vec3(1, 1, 1), origin, direction);
860+
vec4 transfer = cloud_transfer(origin, direction, interval, 0.01);
861+
vec3 background = vec3(0.5, 0.5, 1.0);
862+
fragColor = vec4(background * (1.0 - transfer.a) + transfer.rgb, 1.0);
863+
}")
864+
865+
866+
(defn render-clouds
867+
[width height]
868+
(let [vertices (float-array [1.0 1.0 0.0, -1.0 1.0 0.0, -1.0 -1.0 0.0, 1.0 -1.0 0.0])
869+
indices (int-array [0 1 2 3])
870+
rotation (mulm (rotation-matrix-3d-x (to-radians -25.0)) (rotation-matrix-3d-y (to-radians 30.0)))
871+
vertex-shader (make-shader vertex-test GL20/GL_VERTEX_SHADER)
872+
fragment-sources [ray-box cloud-transfer (cloud-mock 0.3) fragment-cloud]
873+
fragment-shaders (map #(make-shader % GL20/GL_FRAGMENT_SHADER) fragment-sources)
874+
program (apply make-program vertex-shader fragment-shaders)
875+
vao (setup-vao vertices indices)
876+
texture (make-texture width height)]
877+
(setup-point-attribute program)
878+
(framebuffer-render texture width height
879+
(GL20/glUseProgram program)
880+
(GL20/glUniform2f (GL20/glGetUniformLocation program "resolution") width height)
881+
(GL20/glUniformMatrix3fv (GL20/glGetUniformLocation program "rotation") true
882+
(make-float-buffer (mat->float-array rotation)))
883+
(GL20/glUniform1f (GL20/glGetUniformLocation program "focal_length") (/ (* 0.5 width) (tan (to-radians 30.0))))
884+
(GL20/glUniform1f (GL20/glGetUniformLocation program "distance") 4.0)
885+
(GL11/glDrawElements GL11/GL_QUADS (count indices) GL11/GL_UNSIGNED_INT 0))
886+
(let [result (read-texture texture width height)]
887+
(GL11/glDeleteTextures texture)
888+
(teardown-vao vao)
889+
(GL20/glDeleteProgram program)
890+
result)))
891+
892+
893+
(def image (dfn/* 255 (tensor/select (tensor/reshape (tensor/->tensor (render-clouds 640 480)) [480 640 4]) :all :all [2 1 0])))
894+
895+
(bufimg/tensor->image image)
896+
798897
(GLFW/glfwDestroyWindow window)
799898

800899
(GLFW/glfwTerminate)

0 commit comments

Comments
 (0)