shader.mx raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 // Shader source types and GLSL constants.
4 // Vendored from gioui.org/shader v1.0.8 - GLSL100ES only.
5
6 package gio
7
8 // ShaderSources holds the GLSL sources and reflection data for a shader.
9 type ShaderSources struct {
10 Name string
11 GLSL100ES string
12 GLSL150 string
13 Uniforms ShaderUniformsReflection
14 Inputs []ShaderInputLocation
15 Textures []ShaderTextureBinding
16 }
17
18 type ShaderUniformsReflection struct {
19 Locations []ShaderUniformLocation
20 Size int
21 }
22
23 type ShaderTextureBinding struct {
24 Name string
25 Binding int
26 }
27
28 type ShaderUniformLocation struct {
29 Name string
30 Type ShaderDataType
31 Size int
32 Offset int
33 }
34
35 type ShaderInputLocation struct {
36 Name string
37 Location int
38 Type ShaderDataType
39 Size int
40 }
41
42 type ShaderDataType uint8
43
44 const (
45 ShaderDataTypeFloat ShaderDataType = iota
46 ShaderDataTypeInt
47 ShaderDataTypeShort
48 )
49
50 // --- Vendored GLSL100ES shader sources for Gio stencil-and-cover pipeline ---
51
52 func ShaderBlitVert() ShaderSources {
53 return ShaderSources{
54 Name: "blit.vert",
55 Inputs: []ShaderInputLocation{
56 {Name: "pos", Location: 0, Type: 0x0, Size: 2},
57 {Name: "uv", Location: 1, Type: 0x0, Size: 2},
58 },
59 Uniforms: ShaderUniformsReflection{
60 Locations: []ShaderUniformLocation{
61 {Name: "_block.transform", Type: 0x0, Size: 4, Offset: 0},
62 {Name: "_block.uvTransformR1", Type: 0x0, Size: 4, Offset: 16},
63 {Name: "_block.uvTransformR2", Type: 0x0, Size: 4, Offset: 32},
64 {Name: "_block.opacity", Type: 0x0, Size: 1, Offset: 48},
65 {Name: "_block.fbo", Type: 0x0, Size: 1, Offset: 52},
66 },
67 Size: 56,
68 },
69 GLSL100ES: `
70 #version 100
71
72 struct m3x2 {
73 vec3 r0;
74 vec3 r1;
75 };
76 struct Block {
77 vec4 transform;
78 vec4 uvTransformR1;
79 vec4 uvTransformR2;
80 float opacity;
81 float fbo;
82 };
83 uniform Block _block;
84 attribute vec2 pos;
85 varying vec2 vUV;
86 attribute vec2 uv;
87 varying float opacity;
88
89 vec3 transform3x2(m3x2 t, vec3 v) {
90 return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v));
91 }
92 void main() {
93 vec2 p = (pos * _block.transform.xy) + _block.transform.zw;
94 if (_block.fbo != 0.0) {
95 m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0));
96 gl_Position = vec4(transform3x2(param, vec3(p, 0.0)), 1.0);
97 } else {
98 m3x2 param2 = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0));
99 gl_Position = vec4(transform3x2(param2, vec3(p, 0.0)), 1.0);
100 }
101 m3x2 param3 = m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz);
102 vUV = transform3x2(param3, vec3(uv, 1.0)).xy;
103 opacity = _block.opacity;
104 }
105 `,
106 }
107 }
108
109 func ShaderBlitFrag() [3]ShaderSources {
110 return [3]ShaderSources{
111 {
112 Name: "blit.frag",
113 Inputs: []ShaderInputLocation{
114 {Name: "vUV", Location: 0, Type: 0x0, Size: 2},
115 {Name: "opacity", Location: 1, Type: 0x0, Size: 1},
116 },
117 Uniforms: ShaderUniformsReflection{
118 Locations: []ShaderUniformLocation{
119 {Name: "_color.color", Type: 0x0, Size: 4, Offset: 112},
120 },
121 Size: 16,
122 },
123 GLSL100ES: `
124 #version 100
125 precision mediump float;
126 precision highp int;
127 struct Color { vec4 color; };
128 uniform Color _color;
129 varying highp float opacity;
130 varying highp vec2 vUV;
131 void main() { gl_FragData[0] = _color.color * opacity; }
132 `,
133 },
134 {
135 Name: "blit.frag",
136 Inputs: []ShaderInputLocation{
137 {Name: "vUV", Location: 0, Type: 0x0, Size: 2},
138 {Name: "opacity", Location: 1, Type: 0x0, Size: 1},
139 },
140 Uniforms: ShaderUniformsReflection{
141 Locations: []ShaderUniformLocation{
142 {Name: "_gradient.color1", Type: 0x0, Size: 4, Offset: 96},
143 {Name: "_gradient.color2", Type: 0x0, Size: 4, Offset: 112},
144 },
145 Size: 32,
146 },
147 GLSL100ES: `
148 #version 100
149 precision mediump float;
150 precision highp int;
151 struct Gradient { vec4 color1; vec4 color2; };
152 uniform Gradient _gradient;
153 varying highp float opacity;
154 varying highp vec2 vUV;
155 void main() { gl_FragData[0] = mix(_gradient.color1, _gradient.color2, vec4(clamp(vUV.x, 0.0, 1.0))) * opacity; }
156 `,
157 },
158 {
159 Name: "blit.frag",
160 Inputs: []ShaderInputLocation{
161 {Name: "vUV", Location: 0, Type: 0x0, Size: 2},
162 {Name: "opacity", Location: 1, Type: 0x0, Size: 1},
163 },
164 Textures: []ShaderTextureBinding{{Name: "tex", Binding: 0}},
165 GLSL100ES: `
166 #version 100
167 precision mediump float;
168 precision highp int;
169 uniform mediump sampler2D tex;
170 varying highp float opacity;
171 varying highp vec2 vUV;
172 void main() { gl_FragData[0] = texture2D(tex, vUV) * opacity; }
173 `,
174 },
175 }
176 }
177
178 func ShaderCoverVert() ShaderSources {
179 return ShaderSources{
180 Name: "cover.vert",
181 Inputs: []ShaderInputLocation{
182 {Name: "pos", Location: 0, Type: 0x0, Size: 2},
183 {Name: "uv", Location: 1, Type: 0x0, Size: 2},
184 },
185 Uniforms: ShaderUniformsReflection{
186 Locations: []ShaderUniformLocation{
187 {Name: "_block.transform", Type: 0x0, Size: 4, Offset: 0},
188 {Name: "_block.uvCoverTransform", Type: 0x0, Size: 4, Offset: 16},
189 {Name: "_block.uvTransformR1", Type: 0x0, Size: 4, Offset: 32},
190 {Name: "_block.uvTransformR2", Type: 0x0, Size: 4, Offset: 48},
191 {Name: "_block.fbo", Type: 0x0, Size: 1, Offset: 64},
192 },
193 Size: 68,
194 },
195 GLSL100ES: `
196 #version 100
197 struct m3x2 { vec3 r0; vec3 r1; };
198 struct Block { vec4 transform; vec4 uvCoverTransform; vec4 uvTransformR1; vec4 uvTransformR2; float fbo; };
199 uniform Block _block;
200 attribute vec2 pos;
201 varying vec2 vUV;
202 attribute vec2 uv;
203 varying vec2 vCoverUV;
204 vec3 transform3x2(m3x2 t, vec3 v) { return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); }
205 void main() {
206 vec2 p = vec2((pos * _block.transform.xy) + _block.transform.zw);
207 if (_block.fbo != 0.0) {
208 m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0));
209 gl_Position = vec4(transform3x2(param, vec3(p, 0.0)), 1.0);
210 } else {
211 m3x2 param2 = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0));
212 gl_Position = vec4(transform3x2(param2, vec3(p, 0.0)), 1.0);
213 }
214 m3x2 param3 = m3x2(_block.uvTransformR1.xyz, _block.uvTransformR2.xyz);
215 vUV = transform3x2(param3, vec3(uv, 1.0)).xy;
216 vec3 uv3 = vec3(uv, 1.0);
217 vCoverUV = ((uv3 * vec3(_block.uvCoverTransform.xy, 1.0)) + vec3(_block.uvCoverTransform.zw, 0.0)).xy;
218 }
219 `,
220 }
221 }
222
223 func ShaderCoverFrag() [3]ShaderSources {
224 return [3]ShaderSources{
225 {
226 Name: "cover.frag",
227 Inputs: []ShaderInputLocation{
228 {Name: "vCoverUV", Location: 0, Type: 0x0, Size: 2},
229 {Name: "vUV", Location: 1, Type: 0x0, Size: 2},
230 },
231 Uniforms: ShaderUniformsReflection{
232 Locations: []ShaderUniformLocation{
233 {Name: "_color.color", Type: 0x0, Size: 4, Offset: 112},
234 },
235 Size: 16,
236 },
237 Textures: []ShaderTextureBinding{{Name: "cover", Binding: 1}},
238 GLSL100ES: `
239 #version 100
240 precision mediump float;
241 precision highp int;
242 struct Color { vec4 color; };
243 uniform Color _color;
244 uniform mediump sampler2D cover;
245 varying highp vec2 vCoverUV;
246 varying highp vec2 vUV;
247 void main() {
248 gl_FragData[0] = _color.color;
249 float c = min(abs(texture2D(cover, vCoverUV).x), 1.0);
250 gl_FragData[0] *= c;
251 }
252 `,
253 },
254 {
255 Name: "cover.frag",
256 Inputs: []ShaderInputLocation{
257 {Name: "vCoverUV", Location: 0, Type: 0x0, Size: 2},
258 {Name: "vUV", Location: 1, Type: 0x0, Size: 2},
259 },
260 Uniforms: ShaderUniformsReflection{
261 Locations: []ShaderUniformLocation{
262 {Name: "_gradient.color1", Type: 0x0, Size: 4, Offset: 96},
263 {Name: "_gradient.color2", Type: 0x0, Size: 4, Offset: 112},
264 },
265 Size: 32,
266 },
267 Textures: []ShaderTextureBinding{{Name: "cover", Binding: 1}},
268 GLSL100ES: `
269 #version 100
270 precision mediump float;
271 precision highp int;
272 struct Gradient { vec4 color1; vec4 color2; };
273 uniform Gradient _gradient;
274 uniform mediump sampler2D cover;
275 varying highp vec2 vUV;
276 varying highp vec2 vCoverUV;
277 void main() {
278 gl_FragData[0] = mix(_gradient.color1, _gradient.color2, vec4(clamp(vUV.x, 0.0, 1.0)));
279 float c = min(abs(texture2D(cover, vCoverUV).x), 1.0);
280 gl_FragData[0] *= c;
281 }
282 `,
283 },
284 {
285 Name: "cover.frag",
286 Inputs: []ShaderInputLocation{
287 {Name: "vCoverUV", Location: 0, Type: 0x0, Size: 2},
288 {Name: "vUV", Location: 1, Type: 0x0, Size: 2},
289 },
290 Textures: []ShaderTextureBinding{
291 {Name: "tex", Binding: 0},
292 {Name: "cover", Binding: 1},
293 },
294 GLSL100ES: `
295 #version 100
296 precision mediump float;
297 precision highp int;
298 uniform mediump sampler2D tex;
299 uniform mediump sampler2D cover;
300 varying highp vec2 vUV;
301 varying highp vec2 vCoverUV;
302 void main() {
303 gl_FragData[0] = texture2D(tex, vUV);
304 float c = min(abs(texture2D(cover, vCoverUV).x), 1.0);
305 gl_FragData[0] *= c;
306 }
307 `,
308 },
309 }
310 }
311
312 func ShaderStencilVert() ShaderSources {
313 return ShaderSources{
314 Name: "stencil.vert",
315 Inputs: []ShaderInputLocation{
316 {Name: "corner", Location: 0, Type: 0x0, Size: 1},
317 {Name: "maxy", Location: 1, Type: 0x0, Size: 1},
318 {Name: "from", Location: 2, Type: 0x0, Size: 2},
319 {Name: "ctrl", Location: 3, Type: 0x0, Size: 2},
320 {Name: "to", Location: 4, Type: 0x0, Size: 2},
321 },
322 Uniforms: ShaderUniformsReflection{
323 Locations: []ShaderUniformLocation{
324 {Name: "_block.transform", Type: 0x0, Size: 4, Offset: 0},
325 {Name: "_block.pathOffset", Type: 0x0, Size: 2, Offset: 16},
326 },
327 Size: 24,
328 },
329 GLSL100ES: `
330 #version 100
331 struct m3x2 { vec3 r0; vec3 r1; };
332 struct Block { vec4 transform; vec2 pathOffset; };
333 uniform Block _block;
334 attribute float corner;
335 attribute float maxy;
336 attribute vec2 from;
337 attribute vec2 ctrl;
338 attribute vec2 to;
339 varying vec2 vFrom;
340 varying vec2 vCtrl;
341 varying vec2 vTo;
342 vec3 transform3x2(m3x2 t, vec3 v) { return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); }
343 void main() {
344 vec2 from1 = from + _block.pathOffset;
345 vec2 ctrl1 = ctrl + _block.pathOffset;
346 vec2 to1 = to + _block.pathOffset;
347 float maxy1 = maxy + _block.pathOffset.y;
348 float c = corner;
349 vec2 pos;
350 if (c >= 0.375) { c -= 0.5; pos.y = maxy1 + 1.0; } else { pos.y = min(min(from1.y, ctrl1.y), to1.y) - 1.0; }
351 if (c >= 0.125) { pos.x = max(max(from1.x, ctrl1.x), to1.x) + 1.0; } else { pos.x = min(min(from1.x, ctrl1.x), to1.x) - 1.0; }
352 vFrom = from1 - pos; vCtrl = ctrl1 - pos; vTo = to1 - pos;
353 pos = (pos * _block.transform.xy) + _block.transform.zw;
354 m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0));
355 gl_Position = vec4(transform3x2(param, vec3(pos, 0.0)), 1.0);
356 }
357 `,
358 }
359 }
360
361 func ShaderStencilFrag() ShaderSources {
362 return ShaderSources{
363 Name: "stencil.frag",
364 Inputs: []ShaderInputLocation{
365 {Name: "vFrom", Location: 0, Type: 0x0, Size: 2},
366 {Name: "vCtrl", Location: 1, Type: 0x0, Size: 2},
367 {Name: "vTo", Location: 2, Type: 0x0, Size: 2},
368 },
369 GLSL100ES: `
370 #version 100
371 precision mediump float;
372 precision highp int;
373 varying highp vec2 vTo;
374 varying highp vec2 vFrom;
375 varying highp vec2 vCtrl;
376 void main() {
377 float dx = vTo.x - vFrom.x;
378 bool increasing = vTo.x >= vFrom.x;
379 bvec2 _35 = bvec2(increasing);
380 vec2 left = vec2(_35.x ? vFrom.x : vTo.x, _35.y ? vFrom.y : vTo.y);
381 bvec2 _41 = bvec2(increasing);
382 vec2 right = vec2(_41.x ? vTo.x : vFrom.x, _41.y ? vTo.y : vFrom.y);
383 vec2 extent = clamp(vec2(vFrom.x, vTo.x), vec2(-0.5), vec2(0.5));
384 float midx = mix(extent.x, extent.y, 0.5);
385 float x0 = midx - left.x;
386 vec2 p1 = vCtrl - left;
387 vec2 v = right - vCtrl;
388 float t = x0 / (p1.x + sqrt((p1.x * p1.x) + ((v.x - p1.x) * x0)));
389 float y = mix(mix(left.y, vCtrl.y, t), mix(vCtrl.y, right.y, t), t);
390 vec2 d_half = mix(p1, v, vec2(t));
391 float dy = d_half.y / d_half.x;
392 float width = extent.y - extent.x;
393 dy = abs(dy * width);
394 vec4 sides = vec4((dy * 0.5) + y, (dy * (-0.5)) + y, (0.5 - y) / dy, ((-0.5) - y) / dy);
395 sides = clamp(sides + vec4(0.5), vec4(0.0), vec4(1.0));
396 float area = 0.5 * ((((sides.z - (sides.z * sides.y)) + 1.0) - sides.x) + (sides.x * sides.w));
397 area *= width;
398 if (width == 0.0) { area = 0.0; }
399 gl_FragData[0].x = area;
400 }
401 `,
402 }
403 }
404
405 func ShaderIntersectVert() ShaderSources {
406 return ShaderSources{
407 Name: "intersect.vert",
408 Inputs: []ShaderInputLocation{
409 {Name: "pos", Location: 0, Type: 0x0, Size: 2},
410 {Name: "uv", Location: 1, Type: 0x0, Size: 2},
411 },
412 Uniforms: ShaderUniformsReflection{
413 Locations: []ShaderUniformLocation{
414 {Name: "_block.uvTransform", Type: 0x0, Size: 4, Offset: 0},
415 {Name: "_block.subUVTransform", Type: 0x0, Size: 4, Offset: 16},
416 },
417 Size: 32,
418 },
419 GLSL100ES: `
420 #version 100
421 struct m3x2 { vec3 r0; vec3 r1; };
422 struct Block { vec4 uvTransform; vec4 subUVTransform; };
423 uniform Block _block;
424 attribute vec2 pos;
425 varying vec2 vUV;
426 attribute vec2 uv;
427 vec3 transform3x2(m3x2 t, vec3 v) { return vec3(dot(t.r0, v), dot(t.r1, v), dot(vec3(0.0, 0.0, 1.0), v)); }
428 void main() {
429 m3x2 param = m3x2(vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0));
430 vec3 p = transform3x2(param, vec3(pos, 1.0));
431 gl_Position = vec4(p, 1.0);
432 vUV = (uv * _block.subUVTransform.xy) + _block.subUVTransform.zw;
433 vUV = (vUV * _block.uvTransform.xy) + _block.uvTransform.zw;
434 }
435 `,
436 }
437 }
438
439 func ShaderIntersectFrag() ShaderSources {
440 return ShaderSources{
441 Name: "intersect.frag",
442 Inputs: []ShaderInputLocation{
443 {Name: "vUV", Location: 0, Type: 0x0, Size: 2},
444 },
445 Textures: []ShaderTextureBinding{{Name: "cover", Binding: 0}},
446 GLSL100ES: `
447 #version 100
448 precision mediump float;
449 precision highp int;
450 uniform mediump sampler2D cover;
451 varying highp vec2 vUV;
452 void main() { gl_FragData[0].x = abs(texture2D(cover, vUV).x); }
453 `,
454 }
455 }
456