在WebGL片段着色器中绘制网格

时间:2014-07-16 05:08:13

标签: webgl shader fragment-shader

由于某些原因,我正在努力将ZUI从SVG移植到WebGL,并且我想使用片段着色器渲染网格。

以下是我https://dl.dropboxusercontent.com/u/412963/steel/restel_2.mp4

的基本效果

我想要一个每10个单位有一条细线, 1px 线的三角形,每100个单位有一条更粗的 2px 线(这里的单位是任意但与世界空间一致,而不是屏幕空间。)

这是我迄今为止所拥有的,没有视频中的次要粗线(请注意,这实际上是我的开放缓冲区的副本,显然不是正确的):

顶点着色器:

attribute vec3 aVertexPosition;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

varying float vX;
varying float vY;

void main(void) {
  vX = aVertexPosition.x;
  vY = aVertexPosition.y;
  gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}

Fragment Shader:

precision mediump float;

uniform vec2 resolution;
uniform float uZoomFactor;

varying float vX;
varying float vY;

void main(void) {
  float distance = gl_FragCoord.z / gl_FragCoord.w;
  float fuzz = 1.0 / distance;

  float minorLineFreq;

  if (distance > 10.0) {
    minorLineFreq = 1.0;
  } else if (distance > 5.0) {
    minorLineFreq = 1.0;
  } else {
    minorLineFreq = 0.10;
  }

  float xd = mod(vX, minorLineFreq) * 88.1;
  float yd = mod(vY, minorLineFreq) * 88.1;

  if (xd < fuzz) {
    gl_FragColor = vec4(0.0,0.0,0.0,1.0);
  } else if (yd < fuzz) {
    gl_FragColor = vec4(0.0,0.0,0.0,1.0);
  } else {
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
  }
}

它在一定距离处产生近似正确的图像(但请注意带有2px线而不是1px的条带效果):

带有条带的网格 Grid with banding 使用不需要的粗线放大网格 Zoomed in grid with unwanted thicker lines

那么,如何在WebGL片段着色器内部获得一致的网格,每个距离都有1px粗线?

1 个答案:

答案 0 :(得分:5)

我相信我找到了一个可以接受的解决方案。

使用以下顶点(以三角形条绘制):

[ 1.0  1.0  0.0
 -1.0  1.0  0.0
  1.0 -1.0  0.0
 -1.0 -1.0  0.0]

顶点着色器:

attribute vec4 aVertexPosition;

void main(void) {
  gl_Position = aVertexPosition;
}

Fragment Shader:

precision mediump float;

uniform float vpw; // Width, in pixels
uniform float vph; // Height, in pixels

uniform vec2 offset; // e.g. [-0.023500000000000434 0.9794000000000017], currently the same as the x/y offset in the mvMatrix
uniform vec2 pitch;  // e.g. [50 50]

void main() {
  float lX = gl_FragCoord.x / vpw;
  float lY = gl_FragCoord.y / vph;

  float scaleFactor = 10000.0;

  float offX = (scaleFactor * offset[0]) + gl_FragCoord.x;
  float offY = (scaleFactor * offset[1]) + (1.0 - gl_FragCoord.y);

  if (int(mod(offX, pitch[0])) == 0 ||
      int(mod(offY, pitch[1])) == 0) {
    gl_FragColor = vec4(0.0, 0.0, 0.0, 0.5);
  } else {
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
  }
}

给出结果(取决于音高和偏移量),如:

Example Grid output