Changeset 30937 in project


Ignore:
Timestamp:
05/28/14 19:57:53 (6 years ago)
Author:
acharlton
Message:

Update to 0.2.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • wiki/eggref/4/glls

    r30911 r30937  
    22[[toc:]]
    33glls (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
     5In addition to the eponymous module, glls also provides the {{glls-render}} module. {{glls-render}} enhances glls to create automatic rendering functions for each pipeline. When compiled, these rendering functions are created in efficient C, although dynamic functions are also provided. See the section [[#automatic-render-functions|Automatic render functions]] for details.
    46
    57The 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.
     
    2527<record> (shader TYPE SOURCE INPUTS OUTPUTS UNIFORMS PROGRAM)</record>
    2628
    27 Used 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>
     29Used to represent shaders. Returned by {{define-shader}} and {{create-shader}}. It should not typically be necessary to access the slots of this record.
     30
     31<macro> (define-shader SHADER-NAME GLLS-SHADER)</macro>
    3032
    3133Defines, 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}}.
     
    4951<record> (pipeline SHADERS ATTRIBUTES UNIFORMS PROGRAM)</record>
    5052
    51 Created 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 
    55 Defines, 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}}.
     53Created with {{define-pipeline}} 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).
     54
     55<macro> (define-pipeline PIPELINE-NAME . SHADERS)</macro>
     56
     57Defines, 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 {{define-shader}}, 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}}.
     58
     59{{define-pipeline}} has additional effects when used with the {{glls-render}} module (see [[#automatic-render-functions|Automatic render functions]]).
    5660
    5761<procedure> (create-pipeline . SHADERS)</procedure>
     
    6569<procedure> (compile-pipelines)</procedure>
    6670
    67 Compile (as per {{compile-pipeline}}) all the pipelines defined by {{defpipeline}} and {{create-pipeline}}. Must be called while there is an active OpenGL context.
     71Compile (as per {{compile-pipeline}}) all the pipelines defined by {{define-pipeline}} and {{create-pipeline}}. Must be called while there is an active OpenGL context.
    6872
    6973<procedure> (pipeline-uniform UNIFORM PIPELINE)</procedure>
     
    7983
    8084===== Shader syntax
    81 The shaders of glls – the forms that {{defshader}}, {{defpipeline}}, etc. expect – have the following syntax:
     85The shaders of glls – the forms that {{define-shader}}, {{define-pipeline}}, etc. expect – have the following syntax:
    8286
    8387    (<type> [#:version <version>] [#:extensions <extension>] [#:pragmas <pragma>]) <inputs> <body> -> <outputs>
     
    101105For 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.
    102106
    103 It 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.
     107It 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), uniform blocks (for no good reason), {{#error}}, {{#line}}, {{#undef}}, and struct uniforms (implementation reasons). Let me know if there are any features that you find lacking.
    104108
    105109Keep in mind that glls cannot do anything that the GLSL can’t, such as making anonymous or recursive functions.
     
    205209
    206210
     211==== Automatic render functions
     212By using the {{glls-render}} module, you can have glls automatically generate a function that will render an object with your glls shader. {{glls-render}} exports a new {{define-pipeline}} that defines a set of functions used for rendering and managing the objects that will be rendered. {{glls-render}} should not be used with the {{glls}} module: It re-exports everything that you need from {{glls}}.
     213
     214Recalling {{define-pipeline}}:
     215
     216    (define-pipeline PIPELINE-NAME . SHADERS)
     217
     218There is one difference that you need to know when calling {{glls-render}}’s {{define-pipeline}}: All shaders must include a list of the shader’s uniforms since the uniforms are the important information needed to derive rendering functions. This means that if you previously define some shaders (for example: {{my-vertex-shader}} and {{my-fragment-shader}}) and you wish to combine them in a pipeline, you ''must'' include the uniforms in the pipeline definition. This is done with a list that takes the form {{(SHADER uniform: [UNIFORM] ...)}}. This list must be present even if the shader does not use any uniforms. For example:
     219
     220    (define-pipeline my-pipeline
     221      (my-vertex-shader uniform: mvp-matrix inverse-transpose-matrix)
     222      (my-fragment-shader uniform:))
     223
     224Of course, if you are defining the shaders in the pipeline, then a separate list of uniforms is not necessary.
     225
     226{{glls-render}} causes {{define-pipeline}} to define several new functions. First is {{render-PIPELINE-NAME}}. {{render-PIPELINE-NAME}} takes one argument: a renderable object (see [[#renderables|Renderables]]).
     227
     228The {{render-PIPELINE-NAME}} function works differently depending on whether the {{define-pipeline}} has been compiled or interpreted (although the end results should stay the same). When {{define-pipeline}} is compiled, the resulting {{render-PIPELINE-NAME}} function compiled directly to efficient (non-branching) C. When {{define-pipeline}} is interpreted, {{render-PIPELINE-NAME}} calls a generic rendering function that is not nearly as fast.
     229
     230
     231===== Renderables
     232In order to use one of the pre-generated render functions, you must have something to render. That’s why {{define-pipeline}} also defines a function that constructs a renderable object: {{make-SHADER-NAME-renderable}}. This function takes a number of keyword arguments:
     233
     234* {{vao:}} – A VAO such as those returned by [[http://api.call-cc.org/doc/opengl-glew/make-vao|opengl-glew’s {{make-vao}}]]. I.e.: A VAO that binds an array of attributes – for each element in the pipeline – as well as an element array.
     235* {{mode:}} – The drawing mode to use when drawing the elements of the VAO. Must be one of (opengl-glew’s): {{+points+}}, {{+line-strip+}}, {{+line-loop+}}, {{+lines+}}, {{+line-strip-adjacency+}}, {{+triangles+}}, {{+triangle-strip+}}, {{+triangle-fan+}}, {{+triangles-adjacency+}}, {{+triangle-strip-adjacency+}}, or {{+patches+}}. Defaults to {{+triangles+}}.
     236* {{n-elements:}} – The number of elements (vertices) to draw.
     237* {{element-type:}} – The type of the values in the VAO’s element array. Must be one of {{+unsigned-byte+}}, {{+unsigned-short+}}, or `+unsigned-int+.
     238* {{offset:}} – A byte offset to the location of the desired indices to draw.
     239
     240See the [[https://www.opengl.org/sdk/docs/man/html/glDrawElements.xhtml|{{glDrawElements}} documentation]] for more information about these expected arguments.
     241
     242{{make-SHADER-NAME-renderable}} also expects one keyword argument for each uniform in the pipeline. These arguments should either be an f32vector, an s32vector, a u32vector, a pointer to the uniform data, or – in the case of a texture – a fixnum. Even if the uniform is a single value (e.g. a float), it must still be passed as a vector (or a pointer). This lets the value of the uniform be updated independently of the renderable.
     243
     244Additionally, {{define-pipeline}} defines a number of renderable setters for each of the keyword arguments accepted by {{make-SHADER-NAME-renderable}}. These are named:
     245
     246* {{set-SHADER-NAME-renderable-vao!}}
     247* {{set-SHADER-NAME-renderable-mode!}}
     248* {{set-SHADER-NAME-renderable-n-elements!}}
     249* {{set-SHADER-NAME-renderable-element-type!}}
     250* {{set-SHADER-NAME-renderable-offset!}}
     251
     252And for each uniform in the pipeline, {{set-SHADER-NAME-renderable-UNIFORM-NAME!}} is created.
     253
     254
     255===== Fast render functions
     256When compiled, the render function defined by {{define-pipeline}} is actually a combination of three “fast” render functions: a begin render function, a render function, and an end render function. This is done so that, if desired, all of the renderables that belong to the same pipeline may be rendered at the same time, without needing to perform expensive calls like program changes or texture binding more than once. To use these functions, simply call the begin render function with the first renderable, then call the render function on all renderables (including the first), finally calling the end render function (with no arguments) to clean up.
     257
     258{{define-pipeline}} does not define all of these functions separately, but instead defines a single function with which to access them: {{PIPELINE-NAME-fast-render-functions}}. This function returns six values: the begin render function, the render function, the end render function, and pointers to those same C functions in that order.
     259
     260One major assumption must be kept in mind while working with the fast render functions: textures are only bound once. In other words: it is assumed that that all of the renderables belonging to the same pipeline share a common “sprite sheet” (or other shared texture type). If this assumption does not hold true, simply use the standard render function, or call the begin render function for every set of renderables that uses a separate texture.
     261
     262
    207263=== Examples
    208264These 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.
    209265
    210 Aside 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
     266Aside from knowing how to write glls shaders, only one macro, one function, and one record is necessary to use glls: {{define-pipeline}}, {{compile-pipelines}}, and the record {{pipeline}}. This example illustrates this minimal pipeline creation
    211267
    212268<enscript highlight="scheme">   
     
    215271(use glls (prefix glfw3 glfw:) (prefix opengl-glew gl:))
    216272
    217 (defpipeline foo
     273(define-pipeline foo
    218274  ((#:vertex) ((vertex #:vec2) (color #:vec3) #:uniform (mvp #:mat4))
    219275     (define (main) #:void
     
    240296(use glls (prefix glfw3 glfw:) (prefix opengl-glew gl:))
    241297
    242 (defpipeline foo
     298(define-pipeline foo
    243299  ((#:vertex) ((vertex #:vec2) (color #:vec3) #:uniform (mvp #:mat4))
    244300     (define (main) #:void
     
    246302       (set! c color))
    247303     -> ((c #:vec3)))
    248   (#:fragment ((c #:vec3))
     304  ((#:fragment) ((c #:vec3))
    249305     (define (main) #:void
    250306       (set! frag-color (vec4 c 1.0)))
    251307     -> ((frag-color #:vec4))))
    252308
    253 (defshader bar (#:vertex)
     309(define-shader bar (#:vertex)
    254310    ((vertex #:vec2) (color #:vec3) #:uniform (mvp #:mat4))
    255311  (define (main) #:void
     
    258314  -> ((c #:vec3)))
    259315
    260 (defpipeline baz
     316(define-pipeline baz
    261317  bar
    262318  (cadr (pipeline-shaders foo)))
     
    266322   (compile-pipelines)
    267323   (print foo)
    268    (print baz)
    269    (delete-pipeline foo)
     324   (print baz))
    270325</enscript>
    271326
    272327
    273328=== Version history
     329
     330==== Version 0.2.0
     33128 May 2014
     332- Automatic render function generation
     333- Removed {{eval}} from {{defpipeline}} (which broke some things when used in modules)
     334- Renamed {{defpipeline}}, {{defshader}}
     335
    274336
    275337==== Version 0.1.0
     
    296358=== Licence
    297359BSD
    298 
Note: See TracChangeset for help on using the changeset viewer.