CommonLisp+OpenGLで画像を表示したい
単純なプリミティブを描画できるようになると今度は画像を表示してみたくなる。
方法を探っているうちにRAW画像を読み込んで描画する方法がわかったのでサンプルをつくってみた。
開発環境
- Windows 10 x64
- Steel Bank Common Lisp 1.3.12
- QuickLisp
使用技術
cl-opengl
先述の記事でも利用したCommon LispからOpenGLを利用するためのライブラリ。
これがないとなにもはじまりません。
成果物
参考にしたサイトにあるサンプルをみながらごにょごにょしたサンプルコードをGitHubで公開しています。
動かし方
cd ~/quicklisp/local-project
git clone https://github.com/singy15/cl-opengl-image-sample.git
cd cl-opengl-image-sample
sbcl
(ql:quickload :cl-opengl-image-sample)
(cl-opengl-image-sample:main)
こんな感じで画像の読み込みと描画を行う(一部抜粋)。
load-rgba-texture
と描画処理部分は参考サイトからのパクリを参考にした。
cl-opengl-image-sample.lisp
;; Variables.
(defparameter *tex* nil)
;; RAW画像を読み込む関数
(defun load-rgba-texture (path width height)
(let ((texture (cffi:foreign-alloc '%gl:ubyte :count (* width height 4)))
(image (alexandria:read-file-into-byte-vector path)))
(loop for i from 0 to (1- (length image)) do
(setf (cffi:mem-aref texture '%gl:ubyte i) (aref image i)))
texture))
(defmethod glut:display ((window main-window))
; ...
;; 画像(テクスチャ)の描画
(gl:raster-pos 0 0)
(gl:enable :texture-2d)
(gl:enable :blend)
;; アルファチャンネル有効
(gl:blend-func :src-alpha :one-minus-src-alpha)
(let ((x 100.0)
(y 100.0)
(size (/ 32.0 2.0)))
(gl:with-primitive :quads
(gl:tex-coord 0 0)
(gl:vertex (- x size) (- y size) 0)
(gl:tex-coord 1 0)
(gl:vertex (+ x size) (- y size) 0)
(gl:tex-coord 1 1)
(gl:vertex (+ x size) (+ y size) 0)
(gl:tex-coord 0 1)
(gl:vertex (- x size) (+ y size) 0)))
(gl:disable :blend)
(gl:disable :texture-2d)
; ...
)
(defmethod glut:display-window :before ((window main-window))
;; 画像の読み込みとテクスチャの作成
(gl:pixel-store :unpack-alignment 1)
(setf *tex* (car (gl:gen-textures 1)))
(gl:bind-texture :texture-2d *tex*)
(gl:tex-parameter :texture-2d :texture-min-filter :nearest)
(gl:tex-parameter :texture-2d :texture-mag-filter :nearest)
;; アルファチャンネルがあるので:rgbaを指定、RGBAの順で各値(バイト単位)が並んでいる
(gl:tex-image-2d :texture-2d 0 :rgba 32 32 0 :rgba :unsigned-byte (load-rgba-texture "./resource/particle.raw" 32 32)))
実行するとこんな感じの画面がでる。