three.js-为什么似乎多个像素具有相同的gl_FragCoord.xy?

时间:2019-04-04 23:53:42

标签: three.js

根据khronos group documentationgl_FragCoord指定要被着色像素 内的任何位置。

下面,我有一个着色器,可根据像素的模2对着色器着色。我们可以期望看到一种类似于棋盘格的细粒度图案,其中每个像素的颜色都不同于其相邻像素。但是,看起来大多数像素的gl_FragCoord.xy并不是以像素为单位的坐标,而是看起来该值是一个非整数,它是像素的 scaling 坐标。

var canvas;
var scene;
var renderer;
var camera;
var shader;
var quad;

function init() {

  let div = document.getElementById('div');
 
  let newCanvas = document.createElement('CANVAS');
  newCanvas.id = 'canvas';
  let height = 360;
  newCanvas.style.height = height + 'px';
  let width = 1440;
  newCanvas.style.width  = width + 'px';
  newCanvas.style.backgroundColor = 'black';
  newCanvas.style['border-radius'] = '12px';
  div.appendChild(newCanvas);
  div.appendChild(document.createElement('BR'));

  canvas = document.getElementById('canvas');
  scene = new THREE.Scene();
  renderer = new THREE.WebGLRenderer({canvas: canvas});
  camera = new THREE.OrthographicCamera(-0.5*width, 0.5*width, -0.5*height, 0.5*height, 1, 1000);


  shader = new THREE.ShaderMaterial({
    vertexShader: 'void main() { gl_Position = vec4(position,1); }',
    fragmentShader: 'void main(){ gl_FragColor = vec4(mod(gl_FragCoord.xy, 2.0), 0, 1); }'
  });

  quad = new THREE.Mesh(new THREE.PlaneGeometry(width, height), shader);

  scene.add(quad);
}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

var button = document.getElementById('start');
button.onclick = function() { init(); animate(); }
<html>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"></script>
  <div align="center" id="div">
  <button type="button" id="start" class="button" >Start</button>
  </div>
</body>
</html>

我使用了一个非常宽的画布,并且在单击按钮后将该画布附加到了文档上,这似乎很奇怪,但这是在我正在开发的应用程序中实现的方式,所以我认为也许这些功能可能以某种方式导致了问题。

这是一个我从未遇到过的奇怪问题,因此我还没有真正想出任何方法来调试它。到目前为止,我唯一尝试过的操作就是更改四边形的高度和宽度,但这丝毫没有改变输出。

1 个答案:

答案 0 :(得分:0)

我知道了!问题很简单:渲染器未设置为正确的大小(我以为默认大小是画布的大小,但是显然我错了。)

添加

renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);

渲染器声明解决后。

var canvas;
var scene;
var renderer;
var camera;
var shader;
var quad;

function init() {

  let div = document.getElementById('div');
 
  let newCanvas = document.createElement('CANVAS');
  newCanvas.id = 'canvas';
  let height = 360;
  newCanvas.style.height = height + 'px';
  let width = 1440;
  newCanvas.style.width  = width + 'px';
  newCanvas.style.backgroundColor = 'black';
  newCanvas.style['border-radius'] = '12px';
  div.appendChild(newCanvas);
  div.appendChild(document.createElement('BR'));

  canvas = document.getElementById('canvas');
  scene = new THREE.Scene();
  renderer = new THREE.WebGLRenderer({canvas: canvas});
  renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
  camera = new THREE.OrthographicCamera(-0.5*width, 0.5*width, -0.5*height, 0.5*height, 1, 1000);


  shader = new THREE.ShaderMaterial({
    vertexShader: 'void main() { gl_Position = vec4(position,1); }',
    fragmentShader: 'void main(){ gl_FragColor = vec4(mod(gl_FragCoord.xy, 2.0), 0, 1); }'
  });

  quad = new THREE.Mesh(new THREE.PlaneGeometry(width, height), shader);

  scene.add(quad);
}

function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

var button = document.getElementById('start');
button.onclick = function() { init(); animate(); }
<html>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.js"></script>
  <div align="center" id="div">
  <button type="button" id="start" class="button" >Start</button>
  </div>
</body>
</html>