在WebGL着色器

时间:2015-11-25 04:47:33

标签: webgl shader fragment-shader

我希望在WebGL片段着色器中获得xy的准确模数。 xy是整数。

图表mod(x,y),我们得到以下内容: a choppy, irregular chart

用于生成红黑矩形的实际代码是:

gl_FragColor = vec4(mod(
  float(int(v_texCoord[0]*15.))/15.,
  float(int(v_texCoord[1]*15.))/15.
), 0, 0, 1);

其中v_texCoord是vec2,范围从左上角的0,0到右下角的1,1。精度设置为浮动和整数的中介。

阅读图表,我们发现虽然mod(6,6)正确0,但mod(7,7)实际上是7如何解决此问题?

我试图实现自己的mod()函数。但是,它具有相同的错误,并生成相同的图形。

int func_mod(int x, int y) {
    return int(float(x)-float(y)*floor(float(x)/float(y)));
}

在Javascript中,我可以调试它,该功能完美无缺。然后我尝试了一种迭代方法,因为我担心自己会疯狂,而且我不相信浮点除法。

int iter_mod(int x, int y) {
    x = int(abs(float(x))); y = int(abs(float(y)));
    for(int i=0; i>-1; i++) {
        if(x < y) break;
        x = x - y;
    }
    return x;
}

这很有用,但是我无法绘制它,因为当我尝试时它会在环0中出现错误而崩溃。它适用于我需要它的spritesheet计算,但我真的觉得这是一个不正确的解决方案。

(更新:它在我的手机上完美运行。现在这不是我的代码错误,这只是我的问题......)

3 个答案:

答案 0 :(得分:3)

你不是7乘7改装7/15th修改7/15

尝试

gl_FragColor = vec4(mod(
  floor(v_texCoord[0] * 15.),
  floor(v_texCoord[1] * 15.)
) / 15., 0, 0, 1);

您可以看到此处运行的2个版本

function render(num) {
  var gl = document.getElementById("c" + num).getContext("webgl");
  var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

  var arrays = {
    position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
  };
  var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

  var uniforms = {
    resolution: [gl.canvas.width, gl.canvas.height],
    intMod: num == 1,
  };

  gl.useProgram(programInfo.program);
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  twgl.setUniforms(programInfo, uniforms);
  twgl.drawBufferInfo(gl, bufferInfo);
}

render(0)
render(1);
canvas { margin: 1em; height: 100px; width: 150px; }
div { display: inline-block; }
pre { text-align: center; }
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
  <script id="vs" type="notjs">
attribute vec4 position;

void main() {
  gl_Position = position;
}
  </script>
  <script id="fs" type="notjs">
precision mediump float;

uniform vec2 resolution;
uniform bool intMod;

void main() {
  vec2 v_texCoord = gl_FragCoord.xy / resolution.xy;

  if (!intMod) {
  
    gl_FragColor = vec4(mod(
      float(int(v_texCoord[0]*15.))/15.,
      float(int(v_texCoord[1]*15.))/15.
    ), 0, 0, 1);

  } else {

    gl_FragColor = vec4(mod(
      floor(v_texCoord[0]*15.),
      floor(v_texCoord[1]*15.)
    )/15., 0, 0, 1);
    
  }
  
}
  </script>
<div><canvas id="c0"></canvas><pre>mod with fractions</pre></div>
<div><canvas id="c1"></canvas><pre>mod with ints</pre></div>

您还应该注意,mod为0未定义,这意味着您将在不同的GPU上获得不同的结果

答案 1 :(得分:3)

这是一个GLSL函数,它使用应该是整数的(浮点)参数精确计算MOD:

/**
 * Returns accurate MOD when arguments are approximate integers.
 */
float modI(float a,float b) {
    float m=a-floor((a+0.5)/b)*b;
    return floor(m+0.5);
}

请注意,如果&lt; 0且b&gt; 0则返回值将>&gt; = 0,与其他语言不同&#39; %operator。

答案 2 :(得分:1)

请注意,从webGL2开始,我们现在有了int操作,所以这个问题现在可以通过x%y来解决。