30

The only thing I found was Penumbra, which seems to wrap OpenGL 1.1, which I don't care for in the least. It doesn't really have to do anything fancy, a wrapper around LWJGL that exposes OpenGL 3.3/core or OpenGL 4.x/core in a single namespace would suffice - I wouldn't mind a more idiomatic wrapper either, as long as it doesn't do any immediate mode drawing and supports GLSL 3.3 I'm basically happy.

Cubic
  • 14,902
  • 5
  • 47
  • 92
  • I have to wonder, just because Penumbra supports immediate mode, why does that mean you couldn't extend it to do what you want? – BillRobertson42 Oct 29 '12 at 23:15
  • It doesn't "support" immediate mode. It's completely built around it. "Extending" it to do what I want would be the same thing as writing the entire thing myself. Which, by the way, I'm doing right now. In the thin "just give me OpenGL as clojure functions without any particular regard for idiomaticy" kinda way. – Cubic Oct 30 '12 at 09:23
  • @Cubic Do you have a link to your wrapper? I was about to do this as well but if you already have it it would be great to avoid the duplication of work! – prismofeverything Oct 22 '13 at 19:17

4 Answers4

5

Sadly there is nothing other than Penumbra. I would love to have this too...I wonder if we could raise money to fund Zach Tellman to work on it ?!

Hendekagon
  • 4,565
  • 2
  • 28
  • 43
5

Have you checked out Quil? It is Processing for Clojure, and works with OpenGL, too.

https://github.com/quil/quil

hjek
  • 103
  • 4
  • 2
    Not really interested in Processing, and the way I understood it it uses the FF pipeline too. – Cubic Dec 27 '12 at 16:03
  • 1
    [Quil](https://github.com/quil/quil) uses [Processing](http://processing.org/) and Processing uses [JOGL](https://jogamp.org/jogl/www/) for its hardware accelerated 3D rendering support. – Psyllo Oct 22 '13 at 21:20
  • Processing and it's offspun projects are buggy nightmares. I don't recommend doing anything serious in it. – Rebs Feb 17 '19 at 05:19
2

Opengl is dealing with directly calls to gpu, so I do not think is possible to get anything remotely idiomatic for clojure.

Personally, I've been using JOGL (https://jogamp.org/jogl/www/) calls inside clojure code.

So far I am feeling ok with the performance.


****** I have just noticed the existence of Arcadia, which looks great: https://github.com/arcadia-unity/Arcadia

  • When I said _idiomatic_, I don't mean functional. I'm talking more about syntactic sugar to make dealing with these functions a bit more natural-feeling. – Cubic May 15 '13 at 11:28
  • It seems to me that Arcadia is dead. It also doesn't work on Windows because of Unix file-paths. On Linux, the Unity Editor requires a 32-bit `gcc` which I'm sure to most is unacceptable. I didn't try it on a Mac but I assume it's your only option, and still, to use a seemingly dead project. (Which is a shame, I was excited and I'm very interested in Unity3D and Clojure. UE4 too but that's probably too far fetched :P). – MasterMastic Mar 18 '16 at 20:09
  • Arcadia is far from dead as a project. Simply looking at the github repository shows steady and consistant progress. Looking at the twitter feed it's obvious that Unity 5.5 + Mono 4.9 beta development is active and ongoing as well as mobile app packaging. Looking at the Gitter channel shows that some developers are actually using Arcadia for projects, not just prototyping. – huntar Oct 20 '16 at 19:49
0

You can use the Java library LWJGL version 3. There is also legacy LWJGL version 2 which is more widely packaged.

Here is a minimal example using LWJGL version 2:

(ns raw-opengl
  (:import [org.lwjgl BufferUtils]
           [org.lwjgl.opengl Display DisplayMode GL11 GL12 GL13 GL15 GL20 GL30]))

(def vertex-source "#version 130
in mediump vec3 point;
in mediump vec2 texcoord;
out mediump vec2 UV;
void main()
{
  gl_Position = vec4(point, 1);
  UV = texcoord;
}")

(def fragment-source "#version 130
in mediump vec2 UV;
out mediump vec3 fragColor;
uniform sampler2D tex;
void main()
{
  fragColor = texture(tex, UV).rgb;
}")

(def vertices
  (float-array [ 0.5  0.5 0.0 1.0 1.0
                -0.5  0.5 0.0 0.0 1.0
                -0.5 -0.5 0.0 0.0 0.0]))

(def indices
  (int-array [0 1 2]))

(def pixels
  (float-array [0.0 0.0 1.0
                0.0 1.0 0.0
                1.0 0.0 0.0
                1.0 1.0 1.0]))

(defn make-shader [source shader-type]
  (let [shader (GL20/glCreateShader shader-type)]
    (GL20/glShaderSource shader source)
    (GL20/glCompileShader shader)
    (if (zero? (GL20/glGetShaderi shader GL20/GL_COMPILE_STATUS))
      (throw (Exception. (GL20/glGetShaderInfoLog shader 1024))))
    shader))

(defn make-program [vertex-shader fragment-shader]
  (let [program (GL20/glCreateProgram)]
    (GL20/glAttachShader program vertex-shader)
    (GL20/glAttachShader program fragment-shader)
    (GL20/glLinkProgram program)
    (if (zero? (GL20/glGetShaderi program GL20/GL_LINK_STATUS))
      (throw (Exception. (GL20/glGetShaderInfoLog program 1024))))
    program))

(defmacro def-make-buffer [method create-buffer]
  `(defn ~method [data#]
     (let [buffer# (~create-buffer (count data#))]
       (.put buffer# data#)
       (.flip buffer#)
       buffer#)))

(def-make-buffer make-float-buffer BufferUtils/createFloatBuffer)
(def-make-buffer make-int-buffer BufferUtils/createIntBuffer)

(Display/setTitle "mini")
(Display/setDisplayMode (DisplayMode. 320 240))
(Display/create)

(def vertex-shader (make-shader vertex-source GL20/GL_VERTEX_SHADER))
(def fragment-shader (make-shader fragment-source GL20/GL_FRAGMENT_SHADER))
(def program (make-program vertex-shader fragment-shader))

(def vao (GL30/glGenVertexArrays))
(GL30/glBindVertexArray vao)

(def vbo (GL15/glGenBuffers))
(GL15/glBindBuffer GL15/GL_ARRAY_BUFFER vbo)
(def vertices-buffer (make-float-buffer vertices))
(GL15/glBufferData GL15/GL_ARRAY_BUFFER vertices-buffer GL15/GL_STATIC_DRAW)

(def idx (GL15/glGenBuffers))
(GL15/glBindBuffer GL15/GL_ELEMENT_ARRAY_BUFFER idx)
(def indices-buffer (make-int-buffer indices))
(GL15/glBufferData GL15/GL_ELEMENT_ARRAY_BUFFER indices-buffer GL15/GL_STATIC_DRAW)

(GL20/glVertexAttribPointer (GL20/glGetAttribLocation program "point"   ) 3 GL11/GL_FLOAT false (* 5 Float/BYTES) (* 0 Float/BYTES))
(GL20/glVertexAttribPointer (GL20/glGetAttribLocation program "texcoord") 2 GL11/GL_FLOAT false (* 5 Float/BYTES) (* 3 Float/BYTES))
(GL20/glEnableVertexAttribArray 0)
(GL20/glEnableVertexAttribArray 1)

(GL20/glUseProgram program)

(def tex (GL11/glGenTextures))
(GL13/glActiveTexture GL13/GL_TEXTURE0)
(GL11/glBindTexture GL11/GL_TEXTURE_2D tex)
(GL20/glUniform1i (GL20/glGetUniformLocation program "tex") 0)
(def pixel-buffer (make-float-buffer pixels))
(GL11/glTexImage2D GL11/GL_TEXTURE_2D 0 GL11/GL_RGB 2 2 0 GL12/GL_BGR GL11/GL_FLOAT pixel-buffer)
(GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_WRAP_S GL11/GL_REPEAT)
(GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MIN_FILTER GL11/GL_NEAREST)
(GL11/glTexParameteri GL11/GL_TEXTURE_2D GL11/GL_TEXTURE_MAG_FILTER GL11/GL_NEAREST)
(GL30/glGenerateMipmap GL11/GL_TEXTURE_2D)

(GL11/glEnable GL11/GL_DEPTH_TEST)

(while (not (Display/isCloseRequested))
  (GL11/glClearColor 0.0 0.0 0.0 0.0)
  (GL11/glClear (bit-or GL11/GL_COLOR_BUFFER_BIT GL11/GL_DEPTH_BUFFER_BIT))
  (GL11/glDrawElements GL11/GL_TRIANGLES 3 GL11/GL_UNSIGNED_INT 0)
  (Display/update)
  (Thread/sleep 40))

(GL20/glDisableVertexAttribArray 1)
(GL20/glDisableVertexAttribArray 0)

(GL11/glBindTexture GL11/GL_TEXTURE_2D 0)
(GL11/glDeleteTextures tex)

(GL15/glBindBuffer GL15/GL_ELEMENT_ARRAY_BUFFER 0)
(GL15/glDeleteBuffers idx)

(GL15/glBindBuffer GL15/GL_ARRAY_BUFFER 0)
(GL15/glDeleteBuffers vbo)

(GL30/glBindVertexArray 0)
(GL30/glDeleteVertexArrays vao)

(GL20/glDetachShader program vertex-shader)
(GL20/glDetachShader program fragment-shader)
(GL20/glDeleteProgram program)
(GL20/glDeleteShader vertex-shader)
(GL20/glDeleteShader fragment-shader)

(Display/destroy)
wedesoft
  • 2,781
  • 28
  • 25