Edited at

cl-openglでグラフィックス

More than 1 year has passed since last update.

Qiitaの記事をはじめて書きます。

どうぞ生暖かい目で見てやってください。

common lispでグラフィックスやりましょう。

使うのはcl-openglです、QuickLispを使ってインストールします。

まずはcl-openglをインストールしましょう。

cl-openglと一緒にcl-glutとcl-glutもインストールします。

replを起動して。

(ql:quickload :cl-opengl)

(ql:quickload :cl-glu)
(ql:quickload :cl-glut)

とするとインストールされます。

画面にグラフィックを描画するための最低限のソースを書いていきます。


glib.lisp

;; Require libralies

(require 'asdf)
(require 'cl-opengl)
(require 'cl-glut)
(require 'cl-glu)

;; Parameters
(defvar *width* 500)
(defvar *height* 500)

;; USER FUNCTIONS
(defun user-display () ())
(defun user-init () ())
(defun user-idle () ())

;; Derived window class
(defclass main-window (glut:window) ()
(:default-initargs :title "opengl test" :mode '(:double :rgb :depth) :width *width* :height *height*))

;; glut:display
;; Draw.
(defmethod glut:display ((window main-window))
;; Clear buffer
(gl:clear :color-buffer :depth-buffer)

;; Draw shape
;;(glDisable GL_CULL_FACE)
(gl:shade-model :flat)
(gl:normal 0 0 1)

;; user display process
(user-display)

;; Swap buffer
(glut:swap-buffers))

;; glut:idle
;; Application idle.
(defmethod glut:idle ((window main-window))
;; user idling process
(user-idle)
(glut:post-redisplay))

;; glut:reshape
(defmethod glut:reshape ((w main-window) width height)
(gl:viewport 0 0 width height)
(gl:load-identity)
(glu:ortho-2d 0.0 *width* *height* 0.0))

;; glut-display
;; Draw.
(defmethod glut:display-window :before ((window main-window)) )

;; main
;; Main function (Program entry point).
(defun main ()
;; user initalization process
(user-init)
;;(glut:special-func #'key-special)
(glut:display-window (make-instance 'main-window)))



gltest.lisp


(load "glib.lisp")

(defun user-init ())

(defun user-idle ()
(sleep (/ 1.0 60.0)))

(defun user-display ())


では実行してみましょう。

(load "gltest.lisp")

(main)

sample1.png

真っ黒な画面がでてきます。

さて、それではなにか描いてみましょう。

線分を描画する関数を定義します。

;; Draw 2D line.

(defun g2line (x y x2 y2)
(gl:with-primitives :lines
(gl:vertex x y 0.0)
(gl:vertex x2 y2 0.0)))

そしてこんな感じにしてみます。


gltest.lisp

(load "glib.lisp")

(defun user-init ()
(defparameter *theta* 0.0)
(defparameter *length* 100.0)
(defparameter *n* 500)
(defparameter *pi-part* (/ (* 2.0 PI) *n*))
)

(defun user-idle ()
(sleep (/ 1.0 60.0)))

(defun user-display ()
(setf *theta* (+ *theta* 0.01))

(mapcar
(lambda (n)
(let ((rand-len (random 100)))
(g2line (/ *width* 2.0)
(/ *height* 2.0)
(+ (/ *width* 2.0) (* (cos (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
(+ (/ *height* 2.0) (* (sin (+ *theta* (* n *pi-part*))) (+ *length* rand-len))))))
(iota *n*))
)

;; Draw 2D line.
(defun g2line (x y x2 y2)
(gl:with-primitives :lines
(gl:vertex x y 0.0)
(gl:vertex x2 y2 0.0)))

;; iota
(defun iota (m &optional (n 0) (step 1))
(if (>= n m)
nil
(cons n (iota m (+ n step) step))))


sample1.png

ええ、目がチカチカしますね。

線に色をつけるにはこんな感じにします。

;; Draw 2D line.

(defun g2linec (x y x2 y2 r g b)
(gl:with-primitives :lines
(gl:color r g b)
(gl:vertex x y 0.0)
(gl:vertex x2 y2 0.0))
(gl:color 1.0 1.0 1.0))

(defun user-display ()

(setf *theta* (+ *theta* 0.01))

(mapcar
(lambda (n)
(let ((rand-len (random 100)))
(g2linec (/ *width* 2.0)
(/ *height* 2.0)
(+ (/ *width* 2.0) (* (cos (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
(+ (/ *height* 2.0) (* (sin (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
(random 1.0)
(random 1.0)
(random 1.0))))
(iota *n*))
)

sample1.png

もう目がこわれてしまいそうです。

さあ、あなたの目にトドメを刺しましょう ( ̄ー ̄)ニヤリッ

;; draw filled rect

(defun g2fillrectc (x y x2 y2 r g b)
(gl:with-primitives :polygon
(gl:color r g b)
(gl:vertex x y 0.0)
(gl:vertex x2 y 0.0)
(gl:vertex x2 y2 0.0)
(gl:vertex x y2 0.0)
(gl:color 1.0 1.0 1.0)))

(defun user-display ()
(setf *theta* (+ *theta* 0.01))

(g2fillrectc 0.0 0.0 *width* *height*
(random 1.0)
(random 1.0)
(random 1.0))

(mapcar
(lambda (n)
(let ((rand-len (random 100)))
(g2linec (/ *width* 2.0)
(/ *height* 2.0)
(+ (/ *width* 2.0) (* (cos (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
(+ (/ *height* 2.0) (* (sin (+ *theta* (* n *pi-part*))) (+ *length* rand-len)))
(random 1.0)
(random 1.0)
(random 1.0))))
(iota *n*))
)

sample1.png

画像ではわかんないですが、背景がぴかぴかしています。

もう眼球が取れそうです。

さて、今日はここまで。

ここまで読んでくださった皆様、ありがとうございました。

追記1

環境を書き忘れました。

OS:Windows 7 64bit

処理系:SBCL 1.2.15 x86

追記2

cl-openglを使ったグラフィックスライブラリをつくりました。

より手軽にグラフィックスを扱うことができます。