Julio Gudiño
Julio Gudiño

Reputation: 320

2D Color Grid in GLSL Fragment Shader

I'm trying to achieve this pattern in GLSL:

While getting that effect on the X axis is straightforward by scaling, using floor() and mix():

void main() {
  vec2 st = vTexCoord;

  float maxColumns = 100.0;
  float columns = floor(mouse.x * maxColumns);

  // scale the coordinate system to the columns
  st = st * (columns + 1.0);

  float x = floor(st.x) / columns;
  vec3 color = mix(colorA, colorB, min(1.0, x));

  gl_FragColor = vec4(color,1.0);
}

However, achieving rows is not so simple. I tried using the following approach with arrays of colors and dynamic indices:

void main() {
  vec2 st = vTexCoord;

  float maxColumns = 100.0;
  float columns = floor(mouse.x * maxColumns);
  st = st * (columns + 1.0);

  float x = floor(st.x) / columns;

  float maxRows = 2.0;
  float row = mouse.y * maxRows;
  int y = int(floor(row));

  vec3 color = mix(colorsA[y], colorsB[y], min(1.0, x));

  gl_FragColor = vec4(color,1.0);
}

After seeing this error, it looks like I'm taking the wrong approach:

Darn! An error occurred compiling the fragment shader:ERROR: 0:46: '[]' : Index expression must be constant
ERROR: 0:46: '[]' : Index expression must be constant

What would be a correct approach to a 2D color grid in a GLSL fragment shader?

Upvotes: 0

Views: 562

Answers (1)

user128511
user128511

Reputation:

The most obvious question would be, why are you not just using a texture for the entire thing instead of a shader? Texture are a million times more flexible.

In any case you didn't define colorA and colorB but as the error says, in WebGL1, indices must be constant expressions.

If you want to look up values from an array put those values in a texture. Textures are basically arrays.

uniform sampler2D colorA;
uniform sampler2D colorB;
uniform vec2 colorADimensions;
uniform vec2 colorBDimensions;
...

   vec3 cA = texture2D(colorA, (vec2(column, row) + 0.5)  colorADimensions).rgb;
   vec3 cB = texture2D(colorB, (vec2(column, row) + 0.5)  colorBDimensions).rgb;
   vec3 color = mix(cA, cB, min(1.0, x));

This is semi-related: using a texture to emulate indexed palette graphics

otherwise something like this will generate something similar to your image

void main() {
  vec3 colorsA = vec3(1,0,0);
  vec3 colorsB = vec3(0,1,1);
  vec3 colorsC = vec3(0,0,0);
  vec3 colorsD = vec3(1,1,0);
  vec2 vTexCoord = gl_FragCoord.xy / resolution;

  // -----------

  vec2 st = vTexCoord;

  vec2 maxColRows = vec2(100, 2);
  vec2 colRows = floor(mouse * maxColRows);

  st = st * (colRows + 1.0);

  vec2 xy = floor(st) / colRows;

  vec3 colorTop = mix(colorsA, colorsB, min(1.0, xy.x));
  vec3 colorBottom = mix(colorsC, colorsD, min(1.0, xy.x));

  vec3 color = mix(colorTop, colorBottom, min(1.0, xy.y));;
    
  gl_FragColor = vec4(color,1.0);
}

http://glslsandbox.com/e#66911.0

Upvotes: 2

Related Questions