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