summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--chickadee/render/gl.scm11
-rw-r--r--chickadee/render/gpu.scm8
-rw-r--r--chickadee/render/stencil.scm137
-rw-r--r--chickadee/render/viewport.scm2
5 files changed, 158 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index d8e0314..5cd42b5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -65,6 +65,7 @@ SOURCES = \
chickadee/render/gpu.scm \
chickadee/render/blend.scm \
chickadee/render/depth.scm \
+ chickadee/render/stencil.scm \
chickadee/render/texture.scm \
chickadee/render/shader.scm \
chickadee/render/buffer.scm \
diff --git a/chickadee/render/gl.scm b/chickadee/render/gl.scm
index 67d8ef1..0781048 100644
--- a/chickadee/render/gl.scm
+++ b/chickadee/render/gl.scm
@@ -316,3 +316,14 @@ object.")
(%glDepthMask . gl-depth-mask)
(%glDepthRange . gl-depth-range))
+
+;;;
+;;; Stencil Buffer
+;;;
+
+(re-export (%glStencilMask . gl-stencil-mask)
+ (%glStencilMaskSeparate . gl-stencil-mask-separate)
+ (%glStencilFunc . gl-stencil-func)
+ (%glStencilFuncSeparate . gl-stencil-func-separate)
+ (%glStencilOp . gl-stencil-op)
+ (%glStencilOpSeparate . gl-stencil-op-separate))
diff --git a/chickadee/render/gpu.scm b/chickadee/render/gpu.scm
index 3974c68..e01486d 100644
--- a/chickadee/render/gpu.scm
+++ b/chickadee/render/gpu.scm
@@ -37,6 +37,7 @@
gpu-glsl-version
gpu-blend-mode
gpu-depth-test
+ gpu-stencil-test
gpu-framebuffer
gpu-shader
gpu-texture
@@ -45,6 +46,7 @@
gpu-viewport
set-gpu-blend-mode!
set-gpu-depth-test!
+ set-gpu-stencil-test!
set-gpu-framebuffer!
set-gpu-shader!
set-gpu-texture!
@@ -100,6 +102,7 @@ from the GPU's memory."
glsl-version
blend-mode
depth-test
+ stencil-test
framebuffer
shader
textures
@@ -112,6 +115,7 @@ from the GPU's memory."
(glsl-version gpu-glsl-version)
(blend-mode %gpu-blend-mode)
(depth-test %gpu-depth-test)
+ (stencil-test %gpu-stencil-test)
(framebuffer %gpu-framebuffer)
(shader %gpu-shader)
(textures gpu-textures)
@@ -128,6 +132,7 @@ from the GPU's memory."
;; Lazily resolve bindings to avoid circular dependencies.
(blend-module (resolve-interface '(chickadee render blend)))
(depth-module (resolve-interface '(chickadee render depth)))
+ (stencil-module (resolve-interface '(chickadee render stencil)))
(buffer-module (resolve-interface '(chickadee render buffer)))
(framebuffer-module (resolve-interface '(chickadee render framebuffer)))
(shader-module (resolve-interface '(chickadee render shader)))
@@ -150,6 +155,7 @@ from the GPU's memory."
(make-gpu-state (module-ref blend-module 'apply-blend-mode)
'replace)
(make-gpu-state (module-ref depth-module 'apply-depth-test) #f)
+ (make-gpu-state (module-ref stencil-module 'apply-stencil-test) #f)
(make-gpu-state (module-ref framebuffer-module 'apply-framebuffer)
(module-ref framebuffer-module 'null-framebuffer))
(make-gpu-state (module-ref shader-module 'apply-shader)
@@ -168,6 +174,7 @@ from the GPU's memory."
(define-gpu-getter gpu-blend-mode %gpu-blend-mode)
(define-gpu-getter gpu-depth-test %gpu-depth-test)
+(define-gpu-getter gpu-stencil-test %gpu-stencil-test)
(define-gpu-getter gpu-framebuffer %gpu-framebuffer)
(define-gpu-getter gpu-shader %gpu-shader)
(define-gpu-getter gpu-vertex-buffer %gpu-vertex-buffer)
@@ -180,6 +187,7 @@ from the GPU's memory."
(define-gpu-setter set-gpu-blend-mode! %gpu-blend-mode)
(define-gpu-setter set-gpu-depth-test! %gpu-depth-test)
+(define-gpu-setter set-gpu-stencil-test! %gpu-stencil-test)
(define-gpu-setter set-gpu-framebuffer! %gpu-framebuffer)
(define-gpu-setter set-gpu-shader! %gpu-shader)
(define-gpu-setter set-gpu-vertex-buffer! %gpu-vertex-buffer)
diff --git a/chickadee/render/stencil.scm b/chickadee/render/stencil.scm
new file mode 100644
index 0000000..4a20300
--- /dev/null
+++ b/chickadee/render/stencil.scm
@@ -0,0 +1,137 @@
+;;; Chickadee Game Toolkit
+;;; Copyright © 2020 David Thompson <davet@gnu.org>
+;;;
+;;; Chickadee is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published
+;;; by the Free Software Foundation, either version 3 of the License,
+;;; or (at your option) any later version.
+;;;
+;;; Chickadee is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program. If not, see
+;;; <http://www.gnu.org/licenses/>.
+
+(define-module (chickadee render stencil)
+ #:use-module (ice-9 match)
+ #:use-module (gl)
+ #:use-module (chickadee render gl)
+ #:use-module (chickadee render gpu)
+ #:use-module (srfi srfi-9)
+ #:export (make-stencil-test
+ stencil-test?
+ stencil-test-mask-front
+ stencil-test-mask-back
+ stencil-test-function-front
+ stencil-test-function-back
+ stencil-test-function-mask-front
+ stencil-test-function-mask-back
+ stencil-test-reference-front
+ stencil-test-reference-back
+ stencil-test-on-fail-front
+ stencil-test-on-fail-back
+ stencil-test-on-depth-fail-front
+ stencil-test-on-depth-fail-back
+ stencil-test-on-pass-front
+ stencil-test-on-pass-back
+ default-stencil-test
+ apply-stencil-test))
+
+(define-record-type <stencil-test>
+ (%make-stencil-test mask-front mask-back function-front function-back
+ function-mask-front function-mask-back
+ reference-front reference-back
+ on-fail-front on-fail-back
+ on-depth-fail-front on-depth-fail-back
+ on-pass-front on-pass-back)
+ stencil-test?
+ (mask-front stencil-test-mask-front)
+ (mask-back stencil-test-mask-back)
+ (function-front stencil-test-function-front)
+ (function-back stencil-test-function-back)
+ (function-mask-front stencil-test-function-mask-front)
+ (function-mask-back stencil-test-function-mask-back)
+ (reference-front stencil-test-reference-front)
+ (reference-back stencil-test-reference-back)
+ (on-fail-front stencil-test-on-fail-front)
+ (on-fail-back stencil-test-on-fail-back)
+ (on-depth-fail-front stencil-test-on-depth-fail-front)
+ (on-depth-fail-back stencil-test-on-depth-fail-back)
+ (on-pass-front stencil-test-on-pass-front)
+ (on-pass-back stencil-test-on-pass-back))
+
+(define* (make-stencil-test #:key (mask #xFF) (function 'always)
+ (function-mask #xFF) (reference 0)
+ (on-fail 'keep) (on-depth-fail 'keep) (on-pass 'keep)
+ (mask-front mask) (mask-back mask)
+ (function-front function) (function-back function)
+ (function-mask-front function-mask)
+ (function-mask-back function-mask)
+ (reference-front reference)
+ (reference-back reference)
+ (on-fail-front on-fail) (on-fail-back on-fail)
+ (on-depth-fail-front on-depth-fail)
+ (on-depth-fail-back on-depth-fail)
+ (on-pass-front on-pass) (on-pass-back on-pass))
+ (%make-stencil-test mask-front mask-back function-front function-back
+ function-mask-front function-mask-back
+ reference-front reference-back
+ on-fail-front on-fail-back
+ on-depth-fail-front on-depth-fail-back
+ on-pass-front on-pass-back))
+
+(define %default-stencil-test (make-stencil-test))
+
+(define* (apply-stencil-test stencil)
+ (define (symbol->op sym)
+ (match sym
+ ('zero (stencil-op zero))
+ ('keep (stencil-op keep))
+ ('replace (stencil-op replace))
+ ('increment (stencil-op incr))
+ ('increment-wrap (version-1-4 incr-wrap))
+ ('decrement (stencil-op decr))
+ ('decrement-wrap (version-1-4 decr-wrap))
+ ('invert (stencil-op invert))))
+ (define (symbol->function sym)
+ (match sym
+ ('always (stencil-function always))
+ ('never (stencil-function never))
+ ('less-than (stencil-function less))
+ ('equal (stencil-function equal))
+ ('less-than-or-equal (stencil-function lequal))
+ ('greater-than (stencil-function greater))
+ ('greater-than-or-equal (stencil-function gequal))
+ ('not-equal (stencil-function notequal))))
+ (if stencil
+ (begin
+ (gl-enable (enable-cap stencil-test))
+ ;; Mask
+ (gl-stencil-mask-separate (cull-face-mode front)
+ (stencil-test-mask-front stencil))
+ (gl-stencil-mask-separate (cull-face-mode back)
+ (stencil-test-mask-back stencil))
+ ;; Function
+ (gl-stencil-func-separate (cull-face-mode front)
+ (symbol->function
+ (stencil-test-function-front stencil))
+ (stencil-test-reference-front stencil)
+ (stencil-test-function-mask-front stencil))
+ (gl-stencil-func-separate (cull-face-mode back)
+ (symbol->function
+ (stencil-test-function-back stencil))
+ (stencil-test-reference-back stencil)
+ (stencil-test-function-mask-back stencil))
+ ;; Operation
+ (gl-stencil-op-separate (cull-face-mode front)
+ (symbol->op (stencil-test-on-fail-front stencil))
+ (symbol->op (stencil-test-on-depth-fail-front stencil))
+ (symbol->op (stencil-test-on-pass-front stencil)))
+ (gl-stencil-op-separate (cull-face-mode back)
+ (symbol->op (stencil-test-on-fail-back stencil))
+ (symbol->op (stencil-test-on-depth-fail-back stencil))
+ (symbol->op (stencil-test-on-pass-back stencil))))
+ (gl-disable (enable-cap stencil-test))))
diff --git a/chickadee/render/viewport.scm b/chickadee/render/viewport.scm
index 91f50c1..7b9a192 100644
--- a/chickadee/render/viewport.scm
+++ b/chickadee/render/viewport.scm
@@ -53,7 +53,7 @@
(clear-color viewport-clear-color)
(clear-flags viewport-clear-flags))
-(define %default-clear-flags '(color-buffer depth-buffer))
+(define %default-clear-flags '(color-buffer depth-buffer stencil-buffer))
;; Just a fun color from the Dawnbringer 32-color palette instead of
;; boring old black.
(define %default-clear-color tango-light-sky-blue)