Hi,
I am new to Lisp and experimenting with cl-opengl.
I really wanted to see how I can use textures in Lisp
(without having to copy the elements of the array too much).
Strangely there was no example in the cl-opengl package.
So this is what I've come up with.
Copy the code to minimal_texture_example.lisp and run
sbcl --load minimal_texture_example.lisp
It will open a window. Press 't' to create a texture and
'space' to fill it with some pattern.
The interesting part is that with sb-sys:without-gcing
and sb-sys:vector-sap the starting-pointer of the array can be
extracted and used in gl:tex-sub-image-2d.
I also wrote a small wrapper library in C to capture
YUV-frames from a webcam with v4l2 and display the data with
(gl:tex-sub-image-2d :texture-rectangle-nv 0 0 0 +width+ +height+
:ycbcr-mesa :unsigned-short-8-8-rev-mesa
(video-take))
It is quite fast.
Martin Kielhorn
#| use cl-opengl to display some texture |#
(require 'cl-glut)
(defpackage texture-example
(:use :cl))
(in-package texture-example)
(defparameter +width+ 512) ; must be power of two
(defparameter +height+ 512) ; must be power of two
(defparameter +window-width+ 800)
(defparameter +window-height+ 600)
(defclass window (glut:window)
((tex :accessor tex :initform #x0))
(:default-initargs :pos-x 100 :pos-y 100
:width +window-width+ :height +window-height+
:mode '(:double :rgb)))
(defmethod glut:display ((win window))
"draw a textured QUAD"
(gl:clear :color-buffer-bit)
(gl:load-identity)
(gl:with-primitive :quads
(gl:tex-coord 0 0)(gl:vertex +width+ +height+)
(gl:tex-coord 1 0)(gl:vertex 0 +height+)
(gl:tex-coord 1 1)(gl:vertex 0 0)
(gl:tex-coord 0 1)(gl:vertex +width+ 0))
(glut:swap-buffers))
(defmethod glut:reshape ((win window) width height)
(when (zerop height)
(setq height 1))
(gl:viewport 0 0 width height)
(gl:matrix-mode :projection)
(gl:load-identity)
(gl:ortho 0 +window-width+ 0 +window-height+ -1 1)
(gl:matrix-mode :modelview)
(gl:load-identity))
(defvar *field* (make-array (* +width+ +height+ 4)
:element-type '(unsigned-byte 8)))
(defun update-tex (win)
(unless (eq (tex win) #x0)
(loop for i below +width+ do
(loop for j below +height+
do
(let ((pixel (* 4 (+ i (* +width+ j)))))
(setf (aref *field* (+ 0 pixel)) (mod i 215)
(aref *field* (+ 1 pixel)) (mod j 215)))))
(sb-sys:without-gcing
(let ((addr (sb-sys:vector-sap *field*)))
(gl:tex-sub-image-2d :texture-2d 0 0 0 +width+ +height+
:rgba :unsigned-byte addr)))))
(defmethod glut:keyboard ((win window) key x y)
(declare (ignore x y))
(case key
;; switch textures on/off
(#\t (if (eq (tex win) #x0)
(progn (setf (tex win) (first (gl:gen-textures 1)))
(gl:enable :texture-2d)
(gl:bind-texture :texture-2d (tex win))
(gl:tex-parameter :texture-2d :texture-min-filter :nearest)
(gl:tex-parameter :texture-2d :texture-mag-filter :nearest)
(gl:tex-image-2d :texture-2d 0 :rgba +width+ +height+ 0
:rgba :unsigned-byte (cffi:null-pointer)))
(progn (gl:delete-textures (list (tex win)))
(gl:disable :texture-2d)
(setf (tex win) #x0))))
(#\space (update-tex win))
(#\q (glut:destroy-current-window)
(sb-ext:quit)))
(glut:post-redisplay))
(defmethod glut:idle ((win window))
(sleep (/ 1. 30.))
(glut:post-redisplay))
(defun view ()
(glut:display-window (make-instance 'window)))
(view)