CommonLisp
OpenGL

cl-openglでグラフィックス(画像描画編)

More than 1 year has passed since last update.

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)))

実行するとこんな感じの画面がでる。

cl-opengl-image-sample.png

参考にしたサイト

リリカル☆Lisp開発日記-cl-openglで画像出た
Re: Common Lispでパーティクル