source: project/wiki/eggref/4/glls @ 30911

Last change on this file since 30911 was 30911, checked in by acharlton, 6 years ago

Update example for glfw3 0.4.1

File size: 15.8 KB
Line 
1== glls
2[[toc:]]
3glls (GL Lisp Shaders) lets you write [[https://www.opengl.org/documentation/glsl/|GLSL]] (OpenGL Shader Language) shaders in a convenient pseudo-scheme language in Chicken Scheme. The compilation into GLSL happens at compile-time for zero run-time cost. Run-time compilation is also supported. To those that want to dynamically construct shaders: I solute you.
4
5The idea for glls was hugely inspired by [[https://github.com/cbaggers/varjo|Varjo]]. Before learning about Varjo, I had never considered the possibility of writing shaders in anything but the GLSL. Seeing them being written in Lisp was a major, "Of course!" moment.
6
7That said, while this library bears some superficial resemblance to Varjo, the approach is quite different. While Varjo does a lot of work to validate the the lispy-glls expressions (including type checking), glls only performs cursory syntactic checking. The result of this is that one could probably write shaders in Varjo without knowing the GLSL and could be reasonably sure that those shaders would always compile to something that would mostly work. glls makes no such promises, so it is entirely possible to generate GLSL that won’t compile. Being able to understand GLSL code is therefore a prerequisite for successful shader debugging. The GLSL code output by glls is beautifully formatted, thanks to Alex Shinn’s amazing [[http://synthcode.com/scheme/fmt/|fmt]] library. fmt is responsible for far more than just the GLSL formatting, since it is basically a compiler of its own. The compilation portion of glsl is more or less a thin layer on top of fmt.
8
9
10=== Requirements
11* fmt
12* matchable
13* miscmacros
14* opengl-glew
15* srfi-42
16
17
18=== Documentation
19<parameter> glsl-version</parameter>
20
21The default GLSL version used by shaders. Defaults to {{330}}.
22
23
24==== Shaders
25<record> (shader TYPE SOURCE INPUTS OUTPUTS UNIFORMS PROGRAM)</record>
26
27Used to represent shaders. Returned by {{defshader}} and {{create-shader}}. It should not typically be necessary to access the slots of this record.
28
29<macro> (defshader NAME GLLS-SHADER)</macro>
30
31Defines, for syntax and run-time, a new {{shader}} named {{NAME}}. The (unquoted) form {{GLLS-SHADER}} should conform to language defined in the section [[#the-glls-shader-language|The glls shader language]]. Before shaders are used, they must be compiled by OpenGL with {{compile-shader}}.
32
33<procedure> (create-shader GLLS-SHADER #!key INPUTS)</procedure>
34
35Creates a new {{shader}}. The form {{GLLS-SHADER}} should conform to language defined in the section [[#the-glls-shader-language|The glls shader language]]. The key {{INPUTS}} can be used to include additional inputs to the shader. Before shaders are used, they must be compiled by OpenGL with {{compile-shader}}.
36
37<procedure> (compile-glls GLLS-SHADER #!key INPUTS)</procedure>
38
39Returns the source string for a shader. The form {{GLLS-SHADER}} should conform to language defined in the section [[#the-glls-shader-language|The glls shader language]]. The key {{INPUTS}} can be used to include additional inputs to the shader.
40
41<procedure> (compile-shader SHADER)</procedure>
42
43Compile (in OpenGL) {{SHADER}}. Nothing is done if the shader has already been compiled. This typically does not need to be called, since {{compile-pipeline}} does so. Must be called while there is an active OpenGL context.
44
45
46==== Pipelines
47''Pipelines'' are the term that glsl uses to describe a collection of shaders that will be linked together. This is equivalent to a GL ''program'', just less ambiguously named.
48
49<record> (pipeline SHADERS ATTRIBUTES UNIFORMS PROGRAM)</record>
50
51Created with {{defpipeline}} or {{create-pipeline}}, contains the data needed for a pipeline. {{SHADERS}} is the list of shader records. {{ATTRIBUTES}} and {{UNIFORMS}} are lists of the attributes and uniforms of the shader, specified as {{(name . type)}} pairs before compilation (with {{compile-pipeline}} or {{compile-pipelines}}) and {{(name location type)}} lists after compilation. {{PROGRAM}} is the GL ID of the program (always 0 before compilation).
52
53<macro> (defpipeline NAME . SHADERS)</macro>
54
55Defines, for syntax and run-time, a new {{pipeline}} named {{NAME}}. The {{SHADERS}} should either be forms conforming to language defined in the section [[#the-glls-shader-language|The glls shader language]], {{shader}}s defined by {{defshader}}, or a mix of the two. Pipelines must have at least one vertex and one fragment shader to be able to compile. Before pipelines are used, they must be compiled by OpenGL with {{compile-pipeline}} or {{compile-pipelines}}.
56
57<procedure> (create-pipeline . SHADERS)</procedure>
58
59Creates a new {{pipeline}}. The {{SHADERS}} should either be forms conforming to language defined in the section [[#the-glls-shader-language|The glls shader language]], {{shader}}s, or a mix of the two. Pipelines must have at least one vertex and one fragment shader to be able to compile. Before pipelines are used, they must be compiled by OpenGL with {{compile-pipeline}} or {{compile-pipelines}}.
60
61<procedure> (compile-pipeline PIPELINE)</procedure>
62
63Compile (in OpenGL) the {{PIPELINE}} and sets its {{PROGRAM}} slot to the OpenGL program ID. Compiles all of the pipeline’s shaders with {{compile-shader}}. Must be called while there is an active OpenGL context.
64
65<procedure> (compile-pipelines)</procedure>
66
67Compile (as per {{compile-pipeline}}) all the pipelines defined by {{defpipeline}} and {{create-pipeline}}. Must be called while there is an active OpenGL context.
68
69<procedure> (pipeline-uniform UNIFORM PIPELINE)</procedure>
70
71Return the location of {{UNIFORM}}. The {{PIPELINE}} must be compiled before this function can be used.
72
73<procedure> (pipeline-attribute ATTRIBUTE PIPELINE)</procedure>
74
75Return the location of {{ATTRIBUTE}}. The {{PIPELINE}} must be compiled before this function can be used.
76
77
78==== The glls shader language
79
80===== Shader syntax
81The shaders of glls – the forms that {{defshader}}, {{defpipeline}}, etc. expect – have the following syntax:
82
83    (<type> [#:version <version>] [#:extensions <extension>] [#:pragmas <pragma>]) <inputs> <body> -> <outputs>
84
85{{type}} is the keyword type of the shader. It must be one of {{#:vertex}}, {{#:fragment}}, {{#:geometry}}, {{#:tess-control}}, {{#:tess-evaluation}}, or {{#:compute}}.
86
87{{version}} is the integer version number of the shader, i.e. the number you would write at the top of the shader source (e.g. {{#version 410}}). Defaults to the {{glsl-version}} parameter.
88
89{{extensions}} is the list of GLSL extensions desired (in string form). E.g. {{'("GL_EXT_gpu_shader4 : enable")}}. Defaults to {{'()}}
90
91{{pragmas}} is the list of GLSL pragmas desired (in string form). E.g. {{'("optimize(on)")}}. Defaults to {{'()}}
92
93{{inputs}} is a list of the input variables to the shader. These are given in {{(name type)}} lists. The keyword {{#:uniform}} may be used, and all following inputs will be uniforms. E.g.: {{((vertex #:vec2) (color #:vec3) #:uniform (view-matrix #:mat4))}}
94
95{{body}} is the form representing the code of the shader. See the section [[#shader-lisp|Shader Lisp]] for an explanation of the kind of code that is expected.
96
97{{outputs}} is a list of the output variables from the shader. These are given in {{(name type)}} lists.
98
99
100===== Shader Lisp
101For the most part, the Lisp used to define glls shaders looks like Scheme with one notable difference: types must be specified whenever a variable or function is defined. Under the hood, forms are being passed to [[https://wiki.call-cc.org/eggref/4/fmt#c-as-s-expressions|fmt]], so everything that you can do there will work in glls. Details of the Lisp used for shaders is provided in the following sections.
102
103It should be possible to do almost anything in glls that you would want to do with the GLSL. Known exceptions to this is are: layout qualifiers (which I don’t feel are terribly relevant in the context of Scheme, at least not until uniform locations become prevalent), do-while loops (which have no Scheme analog), {{#error}}, {{#line}}, {{#undef}}, and struct uniforms (implementation reasons). Let me know if there are any features that you find lacking.
104
105Keep in mind that glls cannot do anything that the GLSL can’t, such as making anonymous or recursive functions.
106
107
108====== Variables and naming
109Symbols in glls are transformed from a Scheme style into the C style used in the GLSL. Letters after dashes are uppercased (i.e., symbols become camelCased). Symbols prefixed by {{gl:}} in glls become prefixed by {{gl_}} in GLSL.
110
111For programmer-defined variables this has little consequence. The importance of learning the renaming conventions comes when you want to call GLSL functions or variables. Examples of mappings between glls and GLSL names are: {{gl:position}} → {{gl_Position}}, {{float-bits-to-uint}} → {{floatBitsToUint}}, {{shadow-2d-proj-lod}} → {{shadow2DProjLod}}, and {{sampler-2d-ms-array}} → {{sampler2DMSArray}}. Two special cases are {{emit-vertex}} and {{end-primitive}} which are translated into the functions {{EmitVertex}} and {{EndPrimitive}} respectively (which, for some reason, go against the usual GLSL naming conventions).
112
113
114====== Types
115When defining variables or functions in glls, types must be supplied. Basic types (e.g. {{int}}, {{mat2x2}}) are given either as a symbol or keyword (e.g. {{int}}, {{#:mat2x2}}), whichever is preferred. Types with qualifiers (e.g. {{lowp float}}, {{out mediump vec2}}) are given as lists (e.g. {{(lowp float)}}, {{(out mediump vec2)}}).
116
117Arrays are specified as lists beginning with the keyword {{#:array}}. The next element in the list is the type, while the optional third element is the size. E.g. {{(#:array int 5)}}. When used with qualifiers, the array takes the place of the type, e.g. {{(highp (#:array float))}}.
118
119
120====== Functions
121GLSL functions and operators are all called like normal Lisp functions. In almost all cases the GLSL symbol (taking into account the renaming described in [[#variables-and-naming|Variables and naming]] can be used, while many operators can be called with their Scheme counterpart. The only operators that may not be used directly are {{|}}, {{||}}, {{|=}}, {{.}}, {{=}}, and array reference which must be called with their counterparts.
122
123The following is a mapping between glls aliases for GLSL functions and operators:
124
125* {{modulo}}: {{%}}
126* {{expt}}: {{pow}}
127* {{equal?}}, {{eqv?}}, {{eq}}, {{=}}: {{==}}
128* {{set!}}: {{=}}
129* {{and}}: {{&&}}
130* {{or}}: {{||}}
131* {{not}}: {{!}}
132* {{bitwise-and}}, {{bit-or}}: {{&}}
133* {{bitwise-ior}}, {{bit-or}}: {{|}}
134* {{bitwise-xor}}, {{bit-xor}}: {{^}}
135* {{bitwise-not}}, {{bit-not}}: {{~}}
136* {{arithmetic-shift}}: {{<<}}
137* {{field}}: {{.}} (struct field reference, e.g. {{(field point x)}} → {{point.x}})
138* {{swizzle}}: {{.}} (vector swizzling, e.g. {{(swizzle color r g)}} → {{color.rg}})
139* {{array-ref}}, {{vector-ref}}: {{[]}} (array reference, e.g. {{(array-ref a 4)}} → {{a[4]}})
140* {{length}}: {{.length()}} (vector length, e.g. {{(length vec)}} → {{vec.length()}}
141
142
143====== Definition
144Variables, functions, and records (structs) are defined much like they are in Scheme, with additional requirement of including types.
145
146    (define <name> <type> [<value>])
147
148Defines the variable {{name}}. When {{type}} is an array, a vector literal (eg. {{#(1 2 3)}}) may be used.
149
150    (define (<name> [(<parameter> <type>) ...]) <return-type> <body> ...)
151
152Defines the function {{name}}. The last expression in the body of a non-void function is automatically returned.
153
154    (let ((<name> <type> [<value>]) ...) <body> ...)
155
156Defines the supplied variables. When {{type}} is an array, a vector literal (eg. {{#(1 2 3)}}) may be used. Note that, unlike Scheme, the variables created will continue to exist outside of the {{let}} (until the extent of whatever lexical scope the {{let}} exists within). In other words, {{let}} does not introduce scope. Note also that variables defined in {{let}} are within the scope of variables that are subsequently defined in the same {{let}} (i.e. {{let}} functions like {{let*}} in Scheme, and in fact {{let*}} may be used if preferred).
157
158    (define-record <name> (<type> <field>) ...)
159
160Defines the struct {{name}}.
161
162
163====== Control
164The following can be used with identical syntax to scheme:
165
166    (if <test> <true> [<false>])
167   
168    (cond (<test> <result> ...) ... (else <result>))
169   
170    (case <key> ((<value> ...) <result> ...) ... (else <result>))
171   
172    (begin <body> ...)
173
174Keep in mind that they may only be used in the same place as their corresponding GLSL statements, with the exception of {{begin}}, which can only be used where it is possible to have multiple expressions.
175
176
177====== Iteration
178    (for <init> <condition> <update> <body> ...)
179
180GLSL style {{for}} loop.
181
182    (do-times (<var> [<start>] <end>) <body> ...)
183
184Equivalent to {{(for (define <var> #:int <start>) (< <var> <end>) (++ <var>) <body> ...)}}. {{start}} defaults to 0.
185
186    (while <condition> <body> ...)
187
188GLSL style {{while}} loop.
189
190
191====== Jumps
192All GLSL jumps ({{continue}}, {{break}}, {{return}}, {{discard}}) can be called like functions. Return may accept one argument. Keep in mind that the last expression in a non void function is automatically returned.
193
194
195====== Pre-processor
196The following forms can be used to add pre-processor directives:
197
198    (%define <name> [<value>])
199   
200    (%if <test> <true> [<false>])
201   
202    (%ifdef <value> <true> [<false>])
203   
204    (%ifndef <value> <true> [<false>])
205
206
207=== Examples
208These examples depends on the [[http://wiki.call-cc.org/eggref/4/glfw3|glfw3]] egg for window and context creation. The examples presented here illustrate only very basic shader definition and loading. For more complete examples, see the [[https://github.com/AlexCharlton/glls/tree/master/examples|examples directory]] of the source.
209
210Aside from knowing how to write glls shaders, only one macro, one function, and one record is necessary to use glls: {{defpipeline}}, {{compile-pipelines}}, and the record {{pipeline}}. This example illustrates this minimal pipeline creation
211
212<enscript highlight="scheme">    
213(import chicken scheme)
214
215(use glls (prefix glfw3 glfw:) (prefix opengl-glew gl:))
216
217(defpipeline foo
218  ((#:vertex) ((vertex #:vec2) (color #:vec3) #:uniform (mvp #:mat4))
219     (define (main) #:void
220       (set! gl:position (* mvp (vec4 vertex 0.0 1.0)))
221       (set! c color))
222     -> ((c #:vec3)))
223  ((#:fragment) ((c #:vec3))
224     (define (main) #:void
225       (set! frag-color (vec4 c 1.0)))
226     -> ((frag-color #:vec4))))
227
228(glfw:with-window (640 480 "Example" resizable: #f)
229   (gl:init)
230   (compile-pipelines)
231   (print foo)
232   (gl:use-program (pipeline-program foo)))
233</enscript>
234
235This example is similar to the first, but also illustrates the ability to define pipelines in different ways.
236
237<enscript highlight="scheme">    
238(import chicken scheme)
239
240(use glls (prefix glfw3 glfw:) (prefix opengl-glew gl:))
241
242(defpipeline foo
243  ((#:vertex) ((vertex #:vec2) (color #:vec3) #:uniform (mvp #:mat4))
244     (define (main) #:void
245       (set! gl:position (* mvp (vec4 vertex 0.0 1.0)))
246       (set! c color))
247     -> ((c #:vec3)))
248  (#:fragment ((c #:vec3))
249     (define (main) #:void
250       (set! frag-color (vec4 c 1.0)))
251     -> ((frag-color #:vec4))))
252
253(defshader bar (#:vertex)
254    ((vertex #:vec2) (color #:vec3) #:uniform (mvp #:mat4))
255  (define (main) #:void
256    (set! gl:position (* mvp (vec4 vertex 0.0 1.0)))
257    (set! c color))
258  -> ((c #:vec3)))
259
260(defpipeline baz
261  bar
262  (cadr (pipeline-shaders foo)))
263
264(glfw:with-window (640 480 "Example" resizable: #f)
265   (gl:init)
266   (compile-pipelines)
267   (print foo)
268   (print baz)
269   (delete-pipeline foo)
270</enscript>
271
272
273=== Version history
274
275==== Version 0.1.0
276* Initial release
277
278
279=== Roadmap
280Some features that are planned for glls:
281
282* Automatic creation and compilation of rendering functions for a given pipeline
283* Dynamic re-compilation of pipelines suited for REPL sessions
284
285
286=== Source repository
287Source available on [[https://github.com/AlexCharlton/glls|GitHub]].
288
289Bug reports and patches welcome! Bugs can be reported via GitHub or to alex.n.charlton at gmail.
290
291
292=== Author
293Alex Charlton
294
295
296=== Licence
297BSD
298
Note: See TracBrowser for help on using the repository browser.