/
C160_Compute_shaders.kt
96 lines (79 loc) · 3.27 KB
/
C160_Compute_shaders.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
@file:Suppress("UNUSED_EXPRESSION")
@file:Title("Compute shaders")
@file:ParentTitle("Advanced topics")
@file:Order("160")
@file:URL("advancedTopics/ComputeShaders")
package docs.`90_Advanced_Topics`
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.dokgen.annotations.*
import org.openrndr.draw.*
import java.io.File
fun main() {
@Text """
# Compute shaders
Since version 0.3.36 OPENRNDR comes with compute shader functionality
for select platforms. Compute shader support only works on systems
that support OpenGL 4.3 or higher. This excludes all versions of MacOS.
## Example use
This example is composed of two code blocks. The first block is a compute
shader program written in GLSL which produces an `outputImg` by mixing
three input colors:
* A pixel sampled from `inputImg`.
* A `fillColor` sent as a uniform from Kotlin.
* A color generated by calculating the cosine of the coordinates of the pixel
currently being processed.
A typical location for such a compute shader could be
`data/compute-shaders/fill.cs`.
```glsl
#version 430
layout(local_size_x = 1, local_size_y = 1) in;
uniform vec4 fillColor;
uniform float seconds;
layout(rgba8) uniform readonly image2D inputImg;
uniform writeonly image2D outputImg;
void main() {
ivec2 coords = ivec2(gl_GlobalInvocationID.xy);
float v = cos(coords.x * 0.01 + coords.y * 0.01 + seconds) * 0.5 + 0.5;
vec4 wave = vec4(v, 0.0, 0.0, 1.0);
vec4 inputImagePixel = imageLoad(inputImg, coords);
imageStore(outputImg, coords, wave + inputImagePixel + fillColor);
}
```"""
@Media.Image "../media/compute-shaders-001.jpg"
@Text
"""
The second code block is an OPENRNDR program making use of the compute shader:
1. It creates a compute shader program from a file.
1. Initializes the input buffer using a image loaded from disk.
1. Inside the `extend` block (called multiple times per second) some uniforms
are updated: a `fillColor`, the time in
`seconds`, the `inputImg` and the `outputImg`. In this example only
the time changes on every frame.
1. The compute shader is executed, writing the result to the
`outputBuffer`.
1. Finally, the result is displayed by calling `drawer.image()`.
"""
@Application
@ProduceScreenshot("media/compute-shaders-001.jpg")
@Code
application {
program {
val cs = ComputeShader.fromCode(
File("data/compute-shaders/fill.cs").readText(), "cs1"
)
val tempBuffer = loadImage("data/images/cheeta.jpg")
val inputBuffer = colorBuffer(width, height)
tempBuffer.copyTo(inputBuffer)
val outputBuffer = colorBuffer(width, height)
extend {
cs.uniform("fillColor", ColorRGBa.PINK.shade(0.1))
cs.uniform("seconds", seconds)
cs.image("inputImg", 0, inputBuffer.imageBinding(0, ImageAccess.READ))
cs.image("outputImg",1, outputBuffer.imageBinding(0, ImageAccess.WRITE))
cs.execute(outputBuffer.width, outputBuffer.height, 1)
drawer.image(outputBuffer)
}
}
}
}