Skip to content
Browse files


  • Loading branch information...
Shinmera committed Sep 17, 2019
1 parent fcd85a5 commit af6bffcd717ce966b08fd7960abf2f81738831eb
Showing with 51 additions and 76 deletions.
  1. +2 −0 shader-pass.lisp
  2. +49 −76 workbench.lisp
@@ -207,6 +207,8 @@
(gethash (effective-shader-class subject) (assets pass)))

(defmethod coerce-pass-shader ((pass per-object-pass) class type)
;; FIXME: This re-introduces shaders from the pass that were suppressed in the
;; object and vice-versa
(let ((sources (remove NIL (list (effective-shader type class)
(effective-shader type pass)))))
(when sources
@@ -1,97 +1,70 @@
(in-package #:trial)

(defclass workbench (main) ()
(:default-initargs :clear-color (vec 1 1 1 0)))
(:default-initargs :clear-color (vec 0.3 0.3 0.3 0)))

(define-pool workbench
:base 'trial)

(defclass msdf-font (gl-asset texture)
((data :accessor data)))
(define-asset (workbench grid) mesh
(make-line-grid 10 200 200))

(defmethod load ((font msdf-font))
(let ((data (3b-bmfont:read-bmfont (input* font))))
(setf (data font) data)
(setf (internal-format font)
(cond ((3b-bmfont:alpha-chnl data) :RGBA)
((3b-bmfont:blue-chnl data) :RGB)
((3b-bmfont:green-chnl data) :RG)
((3b-bmfont:red-chnl data) :R)
(T (error "WTF"))))
;; FIXME: Multiple pages?
(let ((file (merge-pathnames (getf (aref (3b-bmfont:pages data) 0) :file) (input* font))))
(multiple-value-bind (data width height pixel-type pixel-format)
(load-image file T)
(setf (width font) width)
(setf (height font) height)
(setf (pixel-data font) data)
(setf (pixel-type font) pixel-type)
(setf (pixel-format font) pixel-format)
(allocate font)))))
(define-shader-subject grid (vertex-entity colored-entity)
(:default-initargs :vertex-array (asset 'workbench 'grid)))

(defmethod render-text ((text string) (vbo vertex-buffer) (font msdf-font))
(let ((mesh (make-instance 'vertex-mesh :vertex-type 'trial:textured-vertex)))
(with-vertex-filling (mesh)
(labels ((thunk (x- y- x+ y+ u- v- u+ v+)
(vertex :location (vec2 x- y+) :uv (vec2 u- (- 1 v-)))
(vertex :location (vec2 x- y-) :uv (vec2 u- (- 1 v+)))
(vertex :location (vec2 x+ y+) :uv (vec2 u+ (- 1 v-)))
(vertex :location (vec2 x+ y+) :uv (vec2 u+ (- 1 v-)))
(vertex :location (vec2 x- y-) :uv (vec2 u- (- 1 v+)))
(vertex :location (vec2 x+ y-) :uv (vec2 u+ (- 1 v+)))))
(3b-bmfont:map-glyphs (data font) #'thunk text :y-up T)))
(replace-vertex-data (buffer-data vbo) mesh)
(when (allocated-p vbo)
(resize-buffer vbo T))
(length (vertices mesh))))

(define-shader-entity msdf-text (vertex-entity textured-entity readied)
((text :initarg :text :accessor text)
(texture :initarg :font :accessor font))
(:inhibit-shaders (textured-entity :fragment-shader)))

(defmethod initialize-instance :after ((text msdf-text) &key)
(let ((vbo (make-instance 'vertex-buffer :buffer-data (make-array 0 :adjustable T :element-type 'single-float))))
(setf (vertex-array text) (make-instance 'vertex-array :bindings `((,vbo :size 2 :offset 0 :stride 16)
(,vbo :size 2 :offset 8 :stride 16))
:vertex-form :triangles))))

(defmethod (setf text) :after ((string string) (text msdf-text))
(let ((verts (render-text string (caar (bindings (vertex-array text))) (font text))))
(setf (size (vertex-array text)) verts)
(define-shader-entity lines (vertex-entity)
(:inhibit-shaders (vertex-entity :vertex-shader)))

(defmethod resources-ready ((text msdf-text))
(setf (text text) (text text)))
(defclass line-vertex (vertex)
((next :initarg)))

(define-class-shader (msdf-text :fragment-shader)
"in vec2 texcoord;
uniform sampler2D texture_image;
uniform float pxRange = 4;
uniform vec4 bgColor = vec4(1, 0, 0, 0.5);
uniform vec4 fgColor = vec4(0, 0, 0, 1);
(defmethod initialize-instance :after ((lines lines) &key points)
(let ((mesh (make-instance 'vertex-mesh :vertex-type 'normal-vertex)))
(with-vertex-filling (mesh)
(loop for (a b) on points
while b
do (vertex :location a :normal (v- a b))
(vertex :location b :normal (v- a b))
(vertex :location a :normal (v- b a))
(vertex :location b :normal (v- a b))
(vertex :location b :normal (v- b a))
(vertex :location a :normal (v- b a))))
(setf (vertex-array lines) (change-class mesh 'vertex-array :vertex-form :triangles))))

(define-class-shader (lines :vertex-shader)
"layout(location = 0) in vec3 position;
layout(location = 1) in vec3 direction;
out vec2 line_normal;
uniform float line_width = 3.0;
uniform mat4 model_matrix;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
void main(){
mat4 PVM = projection_matrix * view_matrix * model_matrix;
vec4 screen1 = PVM * vec4(position, 1);
vec4 screen2 = PVM * vec4(position+direction, 1);
line_normal = normalize(screen2.xy/screen2.w-screen1.xy/screen1.w);
line_normal = vec2(-line_normal.y, line_normal.x);
gl_Position = screen1 + vec4(line_normal*line_width/2, 0, 0);

(define-class-shader (lines :fragment-shader)
"in vec2 line_normal;
uniform float feather = 0.2;
out vec4 color;
float median(float r, float g, float b) {
return max(min(r, g), min(max(r, g), b));
void main() {
vec2 msdfUnit = pxRange/vec2(textureSize(texture_image, 0));
vec3 msdfData = texture(texture_image, texcoord).rgb;
float sigDist = median(msdfData.r, msdfData.g, msdfData.b) - 0.5;
sigDist *= dot(msdfUnit, 0.5/fwidth(texcoord));
float opacity = clamp(sigDist + 0.5, 0.0, 1.0);
color = mix(bgColor, fgColor, opacity);
void main(){
color *= (1-length(line_normal))*16;

(define-asset (workbench font) msdf-font

(defmethod setup-scene ((workbench workbench) scene)
(enter (make-instance 'msdf-text :font (asset 'workbench 'font) :text "Thanks for all your good work, |3b|!") scene)eo
(enter (make-instance 'grid) scene)
(enter (make-instance 'lines :points (list (vec 0 0 0) (vec 100 100 0) (vec 100 0 0))) scene)
(enter (make-instance 'editor-camera) scene)
(enter (make-instance 'render-pass) scene))

0 comments on commit af6bffc

Please sign in to comment.
You can’t perform that action at this time.