我将LWJGL与Clojure结合使用,并且难以照亮场景。我正在绘制GLU.Sphere对象,这些对象在关闭照明时可见,但在启用照明时全黑。

我究竟做错了什么?

(ns gltest.core
  (:import [org.lwjgl.opengl Display DisplayMode GL11]
           [org.lwjgl.util.glu GLU Sphere]
           [org.lwjgl Sys]
           [org.lwjgl.input Keyboard]
           [java.nio ByteBuffer ByteOrder])
  (:gen-class))

(declare get-time)

(def temp-buf (ByteBuffer/allocateDirect 16))

(def s (Sphere.))

(def display-state (atom {:mode nil
                          :max-fps 60}))
(def render-state (atom {:last-frame nil
                         :last-fps (float 0)
                         :fps (float 0)}))
(def world-state (atom {:x 400
                        :y 300
                        :rotation 0}))

(defn get-time []
  (/ (* (Sys/getTime) 1000)
        (Sys/getTimerResolution)))

(defn update-fps []
  (let [time (get-time)]
    (when (> (- time (@render-state :last-fps))
             1000)
      (Display/setTitle (format "FPS: %s" (@render-state :fps)))
      (swap! render-state
             assoc :fps (float 0) :last-fps time)))
  (swap! render-state assoc :fps (float (+ (@render-state :fps)
                                           1))))

(defn update [delta]
  (swap! world-state assoc :rotation (+ (:rotation @world-state)
                                        (* (float 0.15) delta)))

  (update-fps))

(defn init-gl []
  (GL11/glClearColor 0.1 0.1 0.1 0.0) ; background
  (GL11/glClearDepth 1)
  (GL11/glDepthFunc GL11/GL_LEQUAL)
  (GL11/glHint GL11/GL_PERSPECTIVE_CORRECTION_HINT GL11/GL_NICEST)
  (GL11/glShadeModel GL11/GL_SMOOTH)
  (GL11/glEnable GL11/GL_DEPTH_TEST)

  ;; fovy, aspect ratio, zNear, zFar
  (let [width (.getWidth (:mode @display-state))
        height (.getHeight (:mode @display-state))
        aspect-ratio (float (/ width height))]
    ;; select projection matrix (controls perspective)
    (GL11/glMatrixMode GL11/GL_PROJECTION)
    (GL11/glLoadIdentity)
    (GLU/gluPerspective 45 aspect-ratio 0.1 100)

    (GL11/glMatrixMode GL11/GL_MODELVIEW)
    (GL11/glLoadIdentity)
    (GL11/glViewport 0 0 width height))

  (GL11/glMaterial GL11/GL_FRONT GL11/GL_SPECULAR (-> temp-buf
                                                      .clear
                                                      .asFloatBuffer
                                                      (.put (float-array [1 1 1 1]))
                                                      .flip))
  (GL11/glMaterial GL11/GL_FRONT GL11/GL_AMBIENT (-> temp-buf
                                                     .clear
                                                     .asFloatBuffer
                                                     (.put (float-array [1 1 1 1]))
                                                     .flip))
  (GL11/glMaterial GL11/GL_FRONT GL11/GL_DIFFUSE (-> temp-buf
                                                     .clear
                                                     .asFloatBuffer
                                                     (.put (float-array [1 1 1 1]))
                                                     .flip))

  (GL11/glMaterialf GL11/GL_FRONT_AND_BACK GL11/GL_SHININESS 10)

  ;; setup light
  (let [ambient-light (float-array [0.5 0.5 0.5 0])
        diffuse-light (float-array [0 1.0 0 0])]
    (GL11/glLight GL11/GL_LIGHT0 GL11/GL_AMBIENT (-> temp-buf
                                                     .clear
                                                     .asFloatBuffer
                                                     (.put ambient-light)
                                                     .flip))
    (GL11/glLight GL11/GL_LIGHT0 GL11/GL_DIFFUSE (-> temp-buf .clear
                                                     .asFloatBuffer
                                                     (.put diffuse-light)
                                                     .flip))
    (GL11/glLight GL11/GL_LIGHT0 GL11/GL_POSITION (-> temp-buf
                                                      .clear
                                                      .asFloatBuffer
                                                      (.put (float-array [0 -1 0 0]))
                                                      .flip)))

  (GL11/glEnable GL11/GL_LIGHTING)
  (GL11/glEnable GL11/GL_LIGHT0)

  (swap! render-state assoc :last-frame (get-time)))

(defn render []
  ;; Clear The Screen And The Depth Buffer
  (GL11/glClear (bit-or GL11/GL_COLOR_BUFFER_BIT GL11/GL_DEPTH_BUFFER_BIT))

  ;; setup camera
  (GL11/glLoadIdentity)
  (GL11/glTranslatef (float 0) (float 0) (float -3))
  (GL11/glRotatef 30 1 0 0)

  (GL11/glPushMatrix)
  (GL11/glTranslatef 0 1 0)
  (.draw s 0.1 50 50)
  (GL11/glPopMatrix))

(defn -main []
  (let [display-mode (first (filter #(and
                                      (== (.getWidth %) 800)
                                      (== (.getHeight %) 600)
                                      (== (.getBitsPerPixel %) 32))
                                    (Display/getAvailableDisplayModes)))]
    (swap! display-state assoc :mode display-mode)

    (Display/setDisplayMode display-mode)
    (Display/setTitle "Test")
    (Display/create))

  (init-gl)

  (while (not (Display/isCloseRequested))
    (let [time (get-time)
          last-frame (@render-state :last-frame)]
      (swap! render-state assoc :last-frame time)
      (update (int (- time last-frame))))
    (render)
    (Display/update)
    (Display/sync (@display-state :max-fps)))

  (Display/destroy)
  (System/exit 0))

最佳答案

在这种情况下,设置ByteBufferglLight调用中使用的glMaterial的顺序可以解决此问题。

// Java
ByteBuffer buf = ByteBuffer.allocateDirect(16);
buf.order(ByteOrder.nativeOrder);

;; Clojure
(def buf (doto (ByteBuffer/allocateDirect 16)
           (.order (ByteOrder/nativeOrder)))

10-05 21:15