From 834b1f71f6917a1e6a6bf85fa7c68039a3c08126 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Wed, 26 Aug 2020 13:43:51 -0400 Subject: render: Add stencil test support. --- Makefile.am | 1 + chickadee/render/gl.scm | 11 ++++ chickadee/render/gpu.scm | 8 +++ chickadee/render/stencil.scm | 137 ++++++++++++++++++++++++++++++++++++++++++ chickadee/render/viewport.scm | 2 +- 5 files changed, 158 insertions(+), 1 deletion(-) create mode 100644 chickadee/render/stencil.scm 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 +;;; +;;; 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 +;;; . + +(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 + (%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) -- cgit v1.2.3