Skip to content

Latest commit

 

History

History
558 lines (493 loc) · 19.5 KB

jogl.org

File metadata and controls

558 lines (493 loc) · 19.5 KB

This file is archived and only kept for reference - DO NOT edit

Contents

JOGL examples

Example: Textured cube & arcball

(ns thi.ng.geom.examples.jogl.ex01
  (:import
   [com.jogamp.opengl GL3 GLAutoDrawable]
   [com.jogamp.newt.event MouseEvent KeyEvent])
  (:require
   [thi.ng.math.core :as m]
   [thi.ng.geom.core :as g]
   [thi.ng.geom.aabb :as a]
   [thi.ng.geom.attribs :as attr]
   [thi.ng.geom.vector :as v]
   [thi.ng.geom.matrix :as mat]
   [thi.ng.geom.gl.core :as gl]
   [thi.ng.geom.gl.arcball :as arc]
   [thi.ng.geom.gl.buffers :as buf]
   [thi.ng.geom.gl.shaders :as sh]
   [thi.ng.geom.gl.glmesh :as glm]
   [thi.ng.geom.gl.jogl.core :as jogl]
   [thi.ng.geom.gl.jogl.constants :as glc]
   [clojure.pprint :refer [pprint]]
   [clojure.java.io :as io]))

(def app (atom nil))

(def shader
  {:vs "
  void main() {
    vCol = vec4(position.xy * 0.5 + 0.5, fract(time), 1.0);
    vUV = uv;
    gl_Position = proj * view * model * vec4(position, 1.0);
  }"
   :fs "out vec4 fragColor;
  void main() {
    fragColor = vCol * texture(tex, vUV);
  }"
   :version  330
   :attribs  {:position :vec3
              :uv       :vec2}
   :varying  {:vCol     :vec4
              :vUV      :vec2}
   :uniforms {:model [:mat4 mat/M44]
              :view  :mat4
              :proj  :mat4
              :tex   [:sampler2D 0]
              :time  :float}
   :state    {:depth-test false
              :blend      true
              :blend-fn   [glc/src-alpha glc/one]}})

(defn init
  [^GLAutoDrawable drawable]
  (let [^GL3 gl (.. drawable getGL getGL3)
        tex     (buf/load-texture gl {:src (io/file "../assets/cubev.png")})
        model   (-> (a/aabb 1)
                    (g/center)
                    (g/as-mesh {:mesh    (glm/gl-mesh 12 #{:uv})
                                :attribs {:uv (attr/face-attribs (attr/uv-cube-map-v 256 false))}})
                    (gl/as-gl-buffer-spec {})
                    (assoc :shader (sh/make-shader-from-spec gl shader))
                    (assoc-in [:shader :state :tex] tex)
                    (gl/make-buffers-in-spec gl glc/static-draw))]
    (swap! app assoc :model model :arcball (arc/arcball {}))))

(defn display
  [^GLAutoDrawable drawable t]
  (let [{:keys [model arcball]} @app
        ^GL3 gl (.. drawable getGL getGL3)]
    (doto gl
      (gl/clear-color-and-depth-buffer 0.3 0.3 0.3 1.0 1.0)
      (gl/draw-with-shader
       (update model :uniforms assoc
               :view (arc/get-view arcball)
               :time (* 0.25 t))))))

(defn dispose [_] (jogl/stop-animator (:anim @app)))

(defn resize
  [_ x y w h]
  (swap! app assoc-in [:model :uniforms :proj] (mat/perspective 45 (/ w h) 0.1 10))
  (swap! app update :arcball arc/resize w h))

(defn key-pressed
  [^KeyEvent e]
  (condp = (.getKeyCode e)
    KeyEvent/VK_ESCAPE (jogl/destroy-window (:window @app))
    nil))

(defn mouse-pressed [^MouseEvent e] (swap! app update :arcball arc/down (.getX e) (.getY e)))

(defn mouse-dragged [^MouseEvent e] (swap! app update :arcball arc/drag (.getX e) (.getY e)))

(defn wheel-moved [^MouseEvent e deltas] (swap! app update :arcball arc/zoom-delta (nth deltas 1)))

(defn -main
  [& args]
  (reset!
   app
   (jogl/gl-window
    {:profile       :gl3
     :samples       4
     :double-buffer true
     :fullscreen    false
     :events        {:init    init
                     :display display
                     :resize  resize
                     :keys    {:press key-pressed}
                     :mouse   {:press mouse-pressed
                               :drag  mouse-dragged
                               :wheel wheel-moved}}}))
  nil)

Example: STL mesh loading

(ns thi.ng.geom.examples.jogl.ex02
  (:import
   [com.jogamp.opengl GL3 GLAutoDrawable]
   [com.jogamp.newt.event MouseEvent KeyEvent])
  (:require
   [thi.ng.math.core :as m]
   [thi.ng.color.core :as col]
   [thi.ng.geom.core :as g]
   [thi.ng.geom.aabb :as a]
   [thi.ng.geom.attribs :as attr]
   [thi.ng.geom.vector :as v]
   [thi.ng.geom.matrix :as mat]
   [thi.ng.geom.quaternion :as q]
   [thi.ng.geom.utils :as gu]
   [thi.ng.geom.mesh.io :as mio]
   [thi.ng.geom.gl.core :as gl]
   [thi.ng.geom.gl.arcball :as arc]
   [thi.ng.geom.gl.shaders :as sh]
   [thi.ng.geom.gl.shaders.phong :as phong]
   [thi.ng.geom.gl.glmesh :as glm]
   [thi.ng.geom.gl.jogl.core :as jogl]
   [thi.ng.geom.gl.jogl.constants :as glc]
   [thi.ng.glsl.core :as glsl]
   [clojure.java.io :as io]))

(def app (atom nil))

(defn load-mesh
  "Loads STL mesh from given path and fits it into centered bounding box."
  [path bounds]
  (with-open [in (io/input-stream path)]
    (->> (mio/read-stl (mio/wrapped-input-stream in) #(glm/gl-mesh % #{:fnorm}))
         vector
         (gu/fit-all-into-bounds (g/center bounds))
         first)))

(defn init
  [^GLAutoDrawable drawable]
  (let [^GL3 gl   (.. drawable getGL getGL3)
        view-rect (gl/get-viewport-rect gl)
        shader    (sh/make-shader-from-spec gl (assoc phong/shader-spec :version 330))
        model     (-> (load-mesh "../assets/suzanne.stl" (a/aabb 2))
                      (gl/as-gl-buffer-spec {})
                      (update :uniforms merge
                              {:lightPos [0 2 2]
                               :view (mat/look-at (v/vec3 0 0 1) (v/vec3) v/V3Y)
                               :shininess 50
                               :wrap 1
                               :ambientCol [0.0 0.1 0.4 0.0]
                               :diffuseCol [0.1 0.5 0.6]
                               :specularCol [0.8 0.3 0.3]})
                      (assoc :shader shader)
                      (gl/make-buffers-in-spec gl glc/static-draw))]
    (swap! app assoc
           :model     model
           :wireframe false
           :arcball   (arc/arcball {:init (m/normalize (q/quat 0.0 0.707 0.707 0))}))))

(defn display
  [^GLAutoDrawable drawable t]
  (let [^GL3 gl (.. drawable getGL getGL3)
        {:keys [model wireframe arcball]} @app
        view    (arc/get-view arcball)]
    (doto gl
      (gl/clear-color-and-depth-buffer col/GRAY 1)
      (.glPolygonMode glc/front-and-back (if wireframe glc/line glc/fill))
      (gl/draw-with-shader (assoc-in model [:uniforms :model] view)))))

(defn resize
  [_ x y w h]
  (swap! app assoc-in [:model :uniforms :proj] (mat/perspective 45 (/ w h) 0.1 10))
  (swap! app update :arcball arc/resize w h))

(defn dispose [_] (jogl/stop-animator (:anim @app)))

(defn key-pressed
  [^KeyEvent e]
  (condp = (.getKeyCode e)
    KeyEvent/VK_ESCAPE (jogl/destroy-window (:window @app))
    (case (.getKeyChar e)
      \w (swap! app update :wireframe not)
      nil)))

(defn mouse-pressed [^MouseEvent e] (swap! app update :arcball arc/down (.getX e) (.getY e)))

(defn mouse-dragged [^MouseEvent e] (swap! app update :arcball arc/drag (.getX e) (.getY e)))

(defn wheel-moved [^MouseEvent e deltas] (swap! app update :arcball arc/zoom-delta (nth deltas 1)))

(defn -main
  [& args]
  (reset!
   app
   (jogl/gl-window
    {:profile       :gl3
     :samples       4
     :double-buffer true
     :fullscreen    false
     :events        {:init    init
                     :display display
                     :dispose dispose
                     :resize  resize
                     :keys    {:press key-pressed}
                     :mouse   {:press mouse-pressed
                               :drag  mouse-dragged
                               :wheel wheel-moved}}}))
  nil)

Example: FBO & FX pipeline

(ns thi.ng.geom.examples.jogl.ex03
  (:import
   [com.jogamp.opengl GL3 GLAutoDrawable]
   [com.jogamp.newt.event MouseEvent KeyEvent])
  (:require
   [thi.ng.math.core :as m]
   [thi.ng.color.core :as col]
   [thi.ng.dstruct.core :as d]
   [thi.ng.geom.core :as g]
   [thi.ng.geom.utils :as gu]
   [thi.ng.geom.rect :as r]
   [thi.ng.geom.aabb :as a]
   [thi.ng.geom.vector :as v]
   [thi.ng.geom.matrix :as mat]
   [thi.ng.geom.quaternion :as q]
   [thi.ng.geom.mesh.io :as mio]
   [thi.ng.geom.gl.core :as gl]
   [thi.ng.geom.gl.arcball :as arc]
   [thi.ng.geom.gl.fx :as fx]
   [thi.ng.geom.gl.fx.bloom :as bloom]
   [thi.ng.geom.gl.glmesh :as glm]
   [thi.ng.geom.gl.shaders :as sh]
   [thi.ng.geom.gl.shaders.phong :as phong]
   [thi.ng.geom.gl.jogl.core :as jogl]
   [thi.ng.geom.gl.jogl.constants :as glc]
   [thi.ng.geom.gl.jogl.buffers :as native]
   [thi.ng.glsl.core :as glsl]
   [clojure.pprint :refer [pprint]]
   [clojure.java.io :as io]))

(def app
  (atom {:mesh    "dev-resources/suzanne.stl"
         :version 330}))

(defn load-mesh
  "Loads STL mesh from given path and fits it into centered bounding box."
  [path bounds]
  (with-open [in (io/input-stream path)]
    (->> #(glm/gl-mesh % #{:fnorm})
         (mio/read-stl (mio/wrapped-input-stream in))
         vector
         (gu/fit-all-into-bounds (g/center bounds))
         first)))

(defn init
  [^GLAutoDrawable drawable]
  (let [{:keys [mesh version]} @app
        ^GL3 gl       (.. drawable getGL getGL3)
        view-rect     (gl/get-viewport-rect gl)
        main-shader   (sh/make-shader-from-spec gl phong/shader-spec version)
        pass-shader   (sh/make-shader-from-spec gl fx/shader-spec version)
        fx-pipe       (fx/init-pipeline gl (bloom/make-pipeline-spec 1280 720 16 version))
        quad          (fx/init-fx-quad gl)
        img-comp      (d/merge-deep
                       quad
                       {:shader (assoc-in (get-in fx-pipe [:shaders :final]) [:state :tex]
                                          (fx/resolve-pipeline-textures fx-pipe [:src :ping]))})
        img-orig      (d/merge-deep
                       quad
                       {:shader (assoc-in pass-shader [:state :tex]
                                          (fx/resolve-pipeline-textures fx-pipe :src))})
        model         (-> (load-mesh mesh (a/aabb 2))
                          (gl/as-gl-buffer-spec {})
                          (d/merge-deep
                           {:uniforms {:view        (mat/look-at (v/vec3 0 0 1) (v/vec3) v/V3Y)
                                       :lightPos    [0 2 0]
                                       :shininess   10
                                       :wrap        0
                                       :ambientCol  [0.0 0.1 0.4 0.0]
                                       :diffuseCol  [0.1 0.6 0.8]
                                       :specularCol [1 1 1]}
                            :shader main-shader})
                          (gl/make-buffers-in-spec gl glc/static-draw))]
    (swap! app merge
           {:model      model
            :fx-pipe    fx-pipe
            :img-comp   img-comp
            :thumbs     (-> fx-pipe :passes butlast reverse vec (conj img-orig))
            :arcball    (arc/arcball {:init (m/normalize (q/quat 0.0 0.707 0.707 0))})})))

(defn display
  [^GLAutoDrawable drawable t]
  (let [^GL3 gl (.. drawable getGL getGL3)
        {:keys [model arcball fx-pipe img-comp thumbs width height]} @app
        src-fbo   (get-in fx-pipe [:fbos :src])
        view-rect (r/rect width height)
        vp        (-> view-rect
                      (gu/fit-all-into-bounds [(r/rect (:width src-fbo) (:height src-fbo))])
                      first
                      (g/center (g/centroid view-rect)))
        fx-pipe   (fx/update-pipeline-pass fx-pipe :final assoc :viewport vp)]
    (gl/bind (:fbo src-fbo))
    (doto gl
      (gl/set-viewport 0 0 (:width src-fbo) (:height src-fbo))
      (gl/clear-color-and-depth-buffer (col/hsva 0 0 0.3) 1)
      (gl/draw-with-shader (assoc-in model [:uniforms :model] (arc/get-view arcball))))
    (gl/unbind (:fbo src-fbo))
    (fx/execute-pipeline gl fx-pipe)
    (loop [y 0, thumbs thumbs]
      (when thumbs
        (gl/set-viewport gl 0 y 160 90)
        (gl/draw-with-shader gl (first thumbs))
        (recur (+ y 90) (next thumbs))))))

(defn key-pressed
  [^KeyEvent e]
  (condp = (.getKeyCode e)
    KeyEvent/VK_ESCAPE (jogl/destroy-window (:window @app))
    nil))

(defn resize
  [_ x y w h]
  (swap! app
         #(-> %
              (assoc-in [:model :uniforms :proj] (mat/perspective 45 (/ w h) 0.1 10))
              (assoc :width w :height h)
              (update :arcball arc/resize w h))))

(defn dispose [_] (jogl/stop-animator (:anim @app)))

(defn mouse-pressed [^MouseEvent e] (swap! app update :arcball arc/down (.getX e) (.getY e)))

(defn mouse-dragged [^MouseEvent e] (swap! app update :arcball arc/drag (.getX e) (.getY e)))

(defn wheel-moved [^MouseEvent e deltas] (swap! app update :arcball arc/zoom-delta (nth deltas 1)))

(defn -main
  [& args]
  (swap! app d/merge-deep
         (jogl/gl-window
          {:profile       :gl3
           :samples       4
           :double-buffer true
           :fullscreen    false
           :events        {:init    init
                           :display display
                           :dispose dispose
                           :resize  resize
                           :keys    {:press key-pressed}
                           :mouse   {:press mouse-pressed
                                     :drag  mouse-dragged
                                     :wheel wheel-moved}}}))
  nil)

Example: Fullscreen quad fragment shader

Basic circular gradient shader

void mainImage(vec2 pos, vec2 aspect) {
  float d = length((mpos - pos) * aspect);
  float l = 1.0 - d * 4.0;
  vec3 col = vec3(l);
  fragColor = vec4(col, 1.0);
}

Sky with interactive sun position

// based on http://glslsandbox.com/e#31148.0
float hash(float n) { return fract(sin(n) * 758.5453); }

float noise(vec3 x) {
    vec3 p = floor(x);
    vec3 f = fract(x);
    // f = f * f * (3.0 - 2.0 * f);
    float n = p.x + p.y * 57.0 + p.z * 800.0;
    return mix(mix(mix(hash(n), hash(n + 1.0), f.x), mix(hash(n + 57.0), hash(n + 58.0), f.x), f.y),
        mix(mix(hash(n + 800.0), hash(n + 801.0), f.x), mix(hash(n + 857.0), hash(n + 858.0), f.x), f.y), f.z);
}

float fbm(vec3 p) {
    float f = 0.0;
    f += 0.50000 * noise(p); p *= 2.02;
    f -= 0.25000 * noise(p); p *= 2.03;
    f += 0.12500 * noise(p); p *= 2.01;
    f += 0.06250 * noise(p); p *= 2.04;
    f -= 0.03125 * noise(p);
    return f / 0.984375;
}

float cloud(vec3 p) {
  p -= fbm(vec3(p.x, p.y, 0.0) * 0.5) * 2.25;
  float a = max(0.0, -(fbm(p * 3.0) * 2.2 - 1.1));
  return a * a;
}

vec3 f2(vec3 c) {
  vec2 mp = vec2(mpos.x, 1.0 - mpos.y);
  c += hash(gl_FragCoord.x + gl_FragCoord.y * 9.9) * 0.01;
  c *= 0.7 - length(gl_FragCoord.xy / resolution.xy - mp) * 0.5;
  float w = length(c);
  return mix(c * vec3(1.0, 1.0, 1.6), vec3(1.4, 1.2, 1.0) * w, w * 1.1 - 0.2);
}

void mainImage(vec2 pos, vec2 aspect) {
  pos.y += 0.2;
  vec2 coord = vec2((pos.x - 0.5) / pos.y, 1.0 / (pos.y + 0.2));
  // coord += fbm(vec3(coord * 18.0, time * 0.001)) * 0.07;
  coord += time * 0.1;
  float q = cloud(vec3(coord, 0.222));
  vec3 col = vec3(0.2, 0.7, 0.8) + vec3(0.2, 0.4, 0.1) * q;
  fragColor = vec4(f2(col), 1.0);
}
(ns thi.ng.geom.examples.jogl.ex04
  (:import
   [com.jogamp.opengl GL3 GLAutoDrawable]
   [com.jogamp.newt.event MouseEvent KeyEvent])
  (:require
   [thi.ng.math.core :as m]
   [thi.ng.color.core :as col]
   [thi.ng.geom.core :as g]
   [thi.ng.geom.vector :as v]
   [thi.ng.geom.matrix :as mat]
   [thi.ng.geom.gl.core :as gl]
   [thi.ng.geom.gl.fx :as fx]
   [thi.ng.geom.gl.shaders :as sh]
   [thi.ng.geom.gl.jogl.core :as jogl]
   [thi.ng.geom.gl.jogl.constants :as glc]
   [clojure.string :as str]))

(def app
  (atom {:version 330
         :example-id :sky
         :mpos (v/vec2)}))

(def shader-examples
  {:basic "
<<ex-shader-basic>>"
   :sky "
<<ex-shader-sky>>"})

(def shader-spec
  {:vs fx/passthrough-vs
   :fs "
//layout(origin_upper_left) in vec4 gl_FragCoord;
out vec4 fragColor;

{{user-code}}

void main() {
  vec2 aspect = vec2(1.0, resolution.y / resolution.x);
  vec2 pos = gl_FragCoord.xy / resolution;
  mainImage(pos, aspect);
}"
   :uniforms {:tex        [:sampler2D 0]
              :time       [:float 0]
              :resolution [:vec2 [1280 720]]
              :mpos       [:vec2 [0 0]]
              :model      [:mat4 mat/M44]}
   :varying  {:vUV :vec2}
   :attribs  {:position [:vec2 0]
              :uv       [:vec2 1]}
   :state    {:depth-test false}})

(defn prepare-example
  [id]
  (update shader-spec :fs str/replace "{{user-code}}" (shader-examples id)))

(defn init
  [^GLAutoDrawable drawable]
  (let [{:keys [example-id version]} @app
        ^GL3 gl   (.. drawable getGL getGL3)
        view-rect (gl/get-viewport-rect gl)
        shader    (sh/make-shader-from-spec gl (prepare-example example-id) version)
        quad      (assoc (fx/init-fx-quad gl) :shader shader)]
    (swap! app merge
           {:quad   quad
            :shader shader})))

(defn display
  [^GLAutoDrawable drawable t]
  (let [^GL3 gl (.. drawable getGL getGL3)
        {:keys [quad width height mpos]} @app]
    (doto gl
      (gl/set-viewport 0 0 width height)
      (gl/draw-with-shader
       (update quad :uniforms merge
               {:time       t
                :mpos       (m/div mpos width height)
                :resolution [width height]})))))

(defn key-pressed
  [^KeyEvent e]
  (condp = (.getKeyCode e)
    KeyEvent/VK_ESCAPE (jogl/destroy-window (:window @app))
    nil))

(defn mouse-moved [^MouseEvent e] (swap! app assoc :mpos (v/vec2 (.getX e) (.getY e))))

(defn resize [_ x y w h] (swap! app assoc :width w :height h))

(defn dispose [_] (jogl/stop-animator (:anim @app)))

(defn -main
  [& args]
  (swap! app merge
         (jogl/gl-window
          {:profile       :gl3
           :samples       4
           :double-buffer true
           :fullscreen    true
           :events        {:init    init
                           :display display
                           :dispose dispose
                           :resize  resize
                           :keys    {:press key-pressed}
                           :mouse   {:move mouse-moved}}}))
  nil)