我将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))
最佳答案
在这种情况下,设置ByteBuffer
和glLight
调用中使用的glMaterial
的顺序可以解决此问题。
// Java
ByteBuffer buf = ByteBuffer.allocateDirect(16);
buf.order(ByteOrder.nativeOrder);
;; Clojure
(def buf (doto (ByteBuffer/allocateDirect 16)
(.order (ByteOrder/nativeOrder)))