Next revision | Previous revision |
guides:gpu [2023/11/01 00:54] – created osnr | guides:gpu [2024/07/16 20:20] (current) – Add time, remove TODO b/c it works admin |
---|
The new 'GPU FFI' which allows you to write vertex and fragment shaders to implement drawing primitives. | ====== GPU FFI ====== |
| |
| The new 'GPU FFI' lets you write vertex and fragment shaders to draw things. |
| |
Here is a very basic shader that you can just paste as a virtual program (or print). It will color a triangle underneath itself green-blue. | Here is a very basic shader that you can just paste as a virtual program (or print). It will color a triangle underneath itself green-blue. |
</code> | </code> |
| |
The first element of the pipeline source object, ''{vec2 p0 vec2 p1 vec2 p2}'', is a list of overall arguments for both shaders. These are accessible from both the vertex and fragment shader. You pass these in at draw time (they're push constants -- sort of like uniforms in GL, but limited in total size to 128 bytes). (The exception is ''%%fn%%''-type arguments, which aren't actually passed in; they're meant to be names of ''%%Gpu::fn%%'' functions you've already made, which are looked up at call time from the surrounding Tcl environment and inlined into the shader. They just fall out and don't map to arguments in Gpu::draw) | The pipeline source object that you pass after ''Wish the GPU compiles pipeline NAME'' has the form ''{ALL-ARGS VERT-SHADER [FRAG-ARGS] FRAG-SHADER}''. |
| |
| The first element of the pipeline source object, ''{vec2 p0 vec2 p1 vec2 p2}'', is a list of overall arguments for both shaders. These are accessible from both the vertex and fragment shader. You pass these in at draw time (they're push constants -- sort of like uniforms in GL, but limited in total size to 128 bytes). |
| |
| (The exception is ''%%fn%%''-type arguments, which aren't actually passed in; they're meant to be names of GPU functions you've wished to be compiled with ''Wish the GPU compiles function NAME {...}''. They just fall out and don't map to arguments in Gpu::draw) |
| |
The second element in the pipeline is the source code of the main function of a vertex shader. It should return a vec2 vertex of a quad in Vulkan triangle-strip vertex order (should be topleft, topright, bottomleft, bottomright, like a Z, not counterclockwise) based on ''%%gl_VertexIndex%%'' (it will be called with vertex index 0, 1, 2, 3). The returned vertex should be in screen coordinates, not in [0, 1]. You can access the builtin ''%%vec2 _resolution%%'' to get resolution of the screen. (In practice, so far we mostly use the vertex shader for clipping so we don't have to touch the whole display on every draw.) | The second element in the pipeline is the source code of the main function of a vertex shader. It should return a vec2 vertex of a quad in Vulkan triangle-strip vertex order (should be topleft, topright, bottomleft, bottomright, like a Z, not counterclockwise) based on ''%%gl_VertexIndex%%'' (it will be called with vertex index 0, 1, 2, 3). The returned vertex should be in screen coordinates, not in [0, 1]. You can access the builtin ''%%vec2 _resolution%%'' to get resolution of the screen. (In practice, so far we mostly use the vertex shader for clipping so we don't have to touch the whole display on every draw.) |
| |
You can make ''%%sampler2D%%''-type arguments if you want to pass an image in; you can make ''%%fn%%'' arguments to a fragment shader as third argument. See the implementations of drawing primitives in virtual-programs/display/*.folk for more examples. | You can make ''%%sampler2D%%''-type arguments if you want to pass an image in; you can make ''%%fn%%'' arguments to a fragment shader as third argument. See the implementations of drawing primitives in virtual-programs/display/*.folk for more examples. |
| |
| ====== Adding functions ====== |
| |
| When you want to use functions, maybe to [[https://iquilezles.org/articles/palettes/|start using fun new color palettes in your shaders]], you can add them like this: |
| |
| <code> |
| # source: https://iquilezles.org/articles/palettes/ |
| # cosine based palette, 4 vec3 params |
| Wish the GPU compiles function "palette" {{float t vec3 a vec3 b vec3 c vec3 d} vec3 { |
| return a + b*cos( 6.28318*(c*t+d) ); |
| }} |
| |
| Wish the GPU compiles pipeline "$this's triangle" { |
| {vec2 p0 vec2 p1 vec2 p2 float u_time} { |
| vec2 vertices[4] = vec2[4](p0, p1, p2, p0); |
| return vertices[gl_VertexIndex]; |
| } {fn palette} { |
| vec3 gradientColor = palette(gl_FragCoord.x, vec3(0.5,0.5,0.5),vec3(sin(u_time),0.5,0.5),vec3(1.0,1.0,1.0),vec3(0.0,sin(u_time),0.20)); |
| return vec4(gradientColor, 1.0); |
| } |
| } |
| |
| Wish $this is outlined blue |
| When $this has region /r/ & the clock time is /t/ { |
| set r' [region move $r down 100%] |
| Wish the GPU draws pipeline "$this's triangle" with arguments [list {*}[lrange [region vertices ${r'}] 0 2] [fmod $t 16384]] |
| }</code> |
| |
| |
==== TODO: Document internal Gpu:: API ==== | ==== TODO: Document internal Gpu:: API ==== |