为什么看起来多个像素具有相同的 gl_FragCoord.xy?



根据 khronos 组的文档,gl_FragCoord指定像素被着色的任何位置。

下面我有一个着色器,它根据像素的坐标模 2 为像素着色。我们可以期待看到一个细粒度的棋盘状图案,其中每个像素的颜色都与其每个邻居不同。但是,看起来大多数像素的gl_FragCoord.xy不是以像素为单位的坐标,而是看起来该值是一个非整数,是像素坐标的某种缩放

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>

我使用了一个非常宽的画布,并且在单击按钮后将画布附加到文档中,这可能看起来很奇怪,但这就是它在我正在处理的应用程序中的实现方式,所以我认为这些功能可能以某种方式导致问题。

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

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

添加

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>

最新更新