为什么GL为您将"gl_Position"除以W而不是让您自己去做? [英] Why does GL divide `gl_Position` by W for you rather than letting you do it yourself?

查看:201
本文介绍了为什么GL为您将"gl_Position"除以W而不是让您自己去做?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:我了解基本数学.我了解各种数学库中的典型perspective函数会生成一个矩阵,该矩阵将z值从-zNear转换为-zFar,再转换回-1到+1,但前提是将结果除以w

Note: I understand the basic math. I understand that the typical perspective function in various math libraries produces a matrix that converts z values from -zNear to -zFar back into -1 to +1 but only if the result is divided by w

具体问题是GPU为您执行此操作而不是您必须自己执行此操作会获得什么?

The specific question is what is gained by the GPU doing this for you rather than you having to do it yourself?

换句话说,可以说GPU并没有神奇地将gl_Position除以gl_Position.w,相反,您必须像在

In other words, lets say the GPU did not magically divide gl_Position by gl_Position.w and that instead you had to do it manually as in

attribute vec4 position;
uniform mat4 worldViewProjection;

void main() {
  gl_Position = worldViewProjection * position;

  // imaginary version of GL where we must divide by W ourselves
  gl_Position /= gl_Position.w;
}

因此,在此假想的GL中有什么坏处?它会起作用还是在将值除以w从而为GPU提供额外的所需信息之前传递值?

What breaks in this imaginary GL because of this? Would it work or is there something about passing in the value before it's been divided by w that provides extra needed info to the GPU?

请注意,如果我确实这样做,纹理映射透视图将中断.

Note that if I actually do it the texture mapping perspective breaks.

"use strict";
var m4 = twgl.m4;
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

var bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 2);

var tex = twgl.createTexture(gl, {
  min: gl.NEAREST,
  mag: gl.NEAREST,
  src: [
    255, 255, 255, 255,
    192, 192, 192, 255,
    192, 192, 192, 255,
    255, 255, 255, 255,
  ],
});

var uniforms = {
  u_diffuse: tex,
};

function render(time) {
  time *= 0.001;
  twgl.resizeCanvasToDisplaySize(gl.canvas);
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  var projection = m4.perspective(
      30 * Math.PI / 180, 
      gl.canvas.clientWidth / gl.canvas.clientHeight, 
      0.5, 10);
  var eye = [1, 4, -6];
  var target = [0, 0, 0];
  var up = [0, 1, 0];

  var camera = m4.lookAt(eye, target, up);
  var view = m4.inverse(camera);
  var viewProjection = m4.multiply(projection, view);
  var world = m4.rotationY(time);

  uniforms.u_worldInverseTranspose = m4.transpose(m4.inverse(world));
  uniforms.u_worldViewProjection = m4.multiply(viewProjection, world);

  gl.useProgram(programInfo.program);
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  twgl.setUniforms(programInfo, uniforms);
  gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);

body {  margin: 0; }
canvas { display: block; width: 100vw; height: 100vh; }

  <script id="vs" type="notjs">
uniform mat4 u_worldViewProjection;
uniform mat4 u_worldInverseTranspose;

attribute vec4 position;
attribute vec3 normal;
attribute vec2 texcoord;

varying vec2 v_texcoord;
varying vec3 v_normal;

void main() {
  v_texcoord = texcoord;
  v_normal = (u_worldInverseTranspose * vec4(normal, 0)).xyz;
  gl_Position = u_worldViewProjection * position;
  gl_Position /= gl_Position.w;
}
  </script>
  <script id="fs" type="notjs">
precision mediump float;

varying vec2 v_texcoord;
varying vec3 v_normal;

uniform sampler2D u_diffuse;

void main() {
  vec4 diffuseColor = texture2D(u_diffuse, v_texcoord);
  vec3 a_normal = normalize(v_normal);
  float l = dot(a_normal, vec3(1, 0, 0));
  gl_FragColor.rgb = diffuseColor.rgb * (l * 0.5 + 0.5);
  gl_FragColor.a = diffuseColor.a;
}
  </script>
  <script src="https://twgljs.org/dist/2.x/twgl-full.min.js"></script>
  <canvas id="c"></canvas>

但是,是因为GPU实际上需要z和w是不同的还是仅仅是GPU设计,并且如果我们进行w自我划分,则不同的设计可以得出所需的信息吗?

But, is that because the GPU actually needs z and w to be different or is it just GPU design and a different design could derive the info it needed if we did the w divide ourselves?

问了这个问题之后,我最终写了这篇说明了这篇文章的文章透视插值.

After asking this question I ended up writing this article that illustrates the perspective interpolation.

推荐答案

原因是,不仅gl_Position被齐次坐标除,而且所有其他内插变化也被除.这称为透视校正插值,要求分割在插值之后(因此在光栅化之后).因此,在顶点着色器中进行分割将根本行不通.另请参见这篇文章.

The reason is, that not only gl_Position gets divided by the homogeneous coordinate, but also all other interpolated varyings. This is called perspective correct interpolation which requires the division to be after the interpolation (and thus after the rasterization). So doing the division in the vertex shader would simply not work. See also this post.

这篇关于为什么GL为您将"gl_Position"除以W而不是让您自己去做?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆