注意:我了解基础数学.我明白,各种数学库中的典型透视函数产生一个矩阵,将z值从-zNear转换为-zFar,返回到-1到1,但只有结果除以w
具体问题是GPU为您做了什么,而不是自己做这个?
换句话说,让我们说GPU并没有通过gl_Position.w神奇地划分gl_Position,而是你手动地像
- 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提供额外的需求信息?
请注意,如果我真的做到了纹理映射透视中断.
- "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,192,],});
- var uniforms = {
- u_diffuse: tex,};
- function render(time) {
- time *= 0.001;
- twgl.resizeCanvasToDisplaySize(gl.canvas);
- gl.viewport(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];
- 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));
- 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?
解决方法
原因在于,不仅将gl_Position除以均匀坐标,还可以将所有其他内插变化除以.这被称为透视正确插值,其需要在插值之后(并且因此在光栅化之后)进行除法.因此,在顶点着色器中进行划分将无法正常工作.参见
this post.