WebGL不会渲染任何内容,正确的矩阵是什么?

德雷克

我试图通过按钮来了解和学习WebGL和计算机图形学,这就是为什么我开始为此工作自己的小库的原因。我花了几天的时间寻找正确的答案,但我无法使其正常工作。

我有列主要矩阵,但我只是尝试渲染基本三角形,但是由于某种原因,无论我通过透视矩阵进行乘法之后,我的顶点Z总是越界。

我在位置0,0,0的空间中设置了一个对象,顶点位置为=

    [
        -0.5, -0.5, 0,
        0.5, -0.5, 0,
        0.5, 0.5, 0
    ]

我的相机设置为60度角fov,的纵横比canvas.width / canvas.height,近平面为1/1000和远平面为50并定位于(0,0,-10)看着我的对象。

在渲染时,我提供给顶点着色器:

Unifrom Matrix4 u_模型

[1 0 0 0
 0 1 0 0
 0 0 1 0
 0 0 0 1]

所以基本上是身份矩阵

统一Matrix4 u_view

[-1  0  0  0
  0  1  0  0
  0  0 -1 -10
  0  0  0  1]

和均匀Matrix4 u_projection

 0.0003282401348280833 0                      -0.3129605393123332  0
 0                     0.0003282401348280833  -0.3129605393123332  0
 0                     0                      -1.0000400008000159 -0.002000040000800016
 0                     0                      -1                   0

我的矩阵模型是

[n11, n12, n13, n14
 n21, n22, n23, n24,
 n31, n32, n33, n34,
 n41, n42, n43, n44 ]

我的透视矩阵计算:

static perspective(fov, aspect, near, far) {
    const r = fov * aspect;
    const l = -4;
    const t = r;
    const b = l;
    const matrix = new Matrix4();
    matrix.n11 = (2 * near) / (r - l);
    matrix.n12 = 0;
    matrix.n13 = (r+l)/(r-l);
    matrix.n14 = 0;
    matrix.n21 = 0;
    matrix.n22 = (2 * near) / (t - b);
    matrix.n23 = (t+b)/(t-b);
    matrix.n24 = 0;
    matrix.n31 = 0;
    matrix.n32 = 0;
    matrix.n33 = (near + far) / (near - far);
    matrix.n34 = (2 * near * far) / (near - far);
    matrix.n41 = 0;
    matrix.n42 = 0;
    matrix.n43 = -1;
    matrix.n44 = 0;
    return matrix;
}

我的顶点着色器

 this.vertexShaderScript =
        '\r\n' +
        'precision highp float;\r\n' +
        'uniform mat4 u_model;\r\n' +
        'uniform mat4 u_view;\r\n' +
        'uniform mat4 u_projection;\r\n' +
        'attribute vec3 a_position;\r\n' +
        'attribute vec4 a_color;\r\n' +
        'varying vec4 v_color;\r\n' +
        'void main(void) {\r\n' +
        '    v_color = a_color;\r\n' +
        '    gl_Position = u_projection * u_view *  u_model * vec4(a_position, 1.0);\r\n' +
        '}\r\n';

和片段着色器

 this.fragmentShaderScript = '\r\n' +
        'precision highp float;\r\n' +
        'varying vec4 v_color;\r\n' +
        'void main(void) {\r\n' +
        '    gl_FragColor = v_color;\r\n' +
        '}\r\n';

我已经检查了视图矩阵,尝试进行转置投影,并使用Spector js检查了是否将矩阵传递给着色器,但均无效果。我还检查了其他答案,但没有一个适合我。

哪个矩阵是错误的?

其余代码可以在我的github上找到:https : //github.com/barteq100/webgl

man

你想达到什么目的?

您的透视功能对我来说毫无意义。它似乎是基于早已弃用的OpenGL 2.1中glFrustum功能的

您会注意到该函数接受6个参数,即左,右,下,上,远。您的数字只有4,而您输入的数字似乎是胡说八道。为什么l代表左硬编码为-4?您为什么认为r应该是fov * aspect

然后,您没有显示设置矩阵的代码,因此我们不知道您如何传递它。WebGL(和OpenGL)矩阵预计将是行主要的。或者换句话说,将在JavaScript中这样指定翻译矩阵

const translationMatrix = [
  1, 0, 0, 0,
  0, 1, 0, 0,
  0, 1, 1, 0,
  x, y, z, 1,
];

OpenGL规范将该矩阵的每一行称为一列,但按照计算机语言标准,它们是行。参见https://webglfundamentals.org/webgl/lessons/webgl-matrix-vs-math.html

如果您想学习WebGL透视矩阵,请尝试本文那篇文章使用了更为常见的透视数学。

无论如何,这是您的透视功能。如果我移动相机,我会发现我正在以一个非常奇怪的角度在原点绘制一个立方体

'use strict';

/* global twgl, m4, requestAnimationFrame, document */

class Matrix4 { }

function perspective(fov, aspect, near, far) {
  const r = fov * aspect;
  const l = -4;
  const t = r;
  const b = l;
  const matrix = new Matrix4();
  matrix.n11 = (2 * near) / (r - l);
  matrix.n12 = 0;
  matrix.n13 = (r+l)/(r-l);
  matrix.n14 = 0;
  matrix.n21 = 0;
  matrix.n22 = (2 * near) / (t - b);
  matrix.n23 = (t+b)/(t-b);
  matrix.n24 = 0;
  matrix.n31 = 0;
  matrix.n32 = 0;
  matrix.n33 = (near + far) / (near - far);
  matrix.n34 = (2 * near * far) / (near - far);
  matrix.n41 = 0;
  matrix.n42 = 0;
  matrix.n43 = -1;
  matrix.n44 = 0;
  return matrix;
}

function toMat(m) {
  return [
    m.n11, m.n21, m.n31, m.n41,
    m.n12, m.n22, m.n32, m.n42,
    m.n13, m.n23, m.n33, m.n43,
    m.n14, m.n24, m.n34, m.n44,
  ];
}

const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl');

const vs = `
attribute vec4 position;
attribute vec3 normal;
attribute vec2 texcoord;

uniform mat4 projection;
uniform mat4 modelView;

varying vec3 v_normal;
varying vec2 v_texcoord;

void main() {
  gl_Position = projection * modelView * position;
  v_normal = mat3(modelView) * normal;
  v_texcoord = texcoord;
}
`;

const fs = `
precision highp float;

varying vec3 v_normal;
varying vec2 v_texcoord;
varying float v_modelId;

void main() {
  vec3 lightDirection = normalize(vec3(1, 2, -3));  // arbitrary light direction
  
  float l = dot(lightDirection, normalize(v_normal)) * .5 + .5;
  gl_FragColor = vec4(vec3(0,1,0) * l, 1);
}
`;

// compile shader, link, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);

// make some vertex data
const bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 1);

function render(time) {
  time *= 0.001;  // seconds
  
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);

  const fov = Math.PI * 0.25;
  const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
  const near = 0.1;
  const far = 100;
  const projection = toMat(perspective(fov, aspect, near, far));
  
  const camera = m4.translation([0, 0, 1]);
  const view = m4.inverse(camera);
  let modelView = m4.rotateY(view, time);

  gl.useProgram(programInfo.program);
  
  // calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  
  // calls gl.activeTexture, gl.bindTexture, gl.uniformXXX
  twgl.setUniforms(programInfo, {
    projection,
    modelView,
  });  
  
  // calls gl.drawArrays or gl.drawElements
  twgl.drawBufferInfo(gl, bufferInfo);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>

如果将透视功能更改为更传统的功能,那么在移动相机后我将获得更正常的功能

'use strict';

/* global twgl, m4, requestAnimationFrame, document */

class Matrix4 { }

function perspective(fov, aspect, near, far) {

  const f = Math.tan(Math.PI * 0.5 - 0.5 * fov);
  const rangeInv = 1.0 / (near - far);

  const matrix = new Matrix4();
  matrix.n11 = f / aspect;
  matrix.n12 = 0;
  matrix.n13 = 0;
  matrix.n14 = 0;
  matrix.n21 = 0;
  matrix.n22 = f;
  matrix.n23 = 0;
  matrix.n24 = 0;
  matrix.n31 = 0;
  matrix.n32 = 0;
  matrix.n33 = (near + far) * rangeInv;
  matrix.n34 = near * far * rangeInv * 2;
  matrix.n41 = 0;
  matrix.n42 = 0;
  matrix.n43 = -1;
  matrix.n44 = 0;
  return matrix;
}

function toMat(m) {
  return [
    m.n11, m.n21, m.n31, m.n41,
    m.n12, m.n22, m.n32, m.n42,
    m.n13, m.n23, m.n33, m.n43,
    m.n14, m.n24, m.n34, m.n44,
  ];
}

const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl');

const vs = `
attribute vec4 position;
attribute vec3 normal;
attribute vec2 texcoord;

uniform mat4 projection;
uniform mat4 modelView;

varying vec3 v_normal;
varying vec2 v_texcoord;

void main() {
  gl_Position = projection * modelView * position;
  v_normal = mat3(modelView) * normal;
  v_texcoord = texcoord;
}
`;

const fs = `
precision highp float;

varying vec3 v_normal;
varying vec2 v_texcoord;
varying float v_modelId;

void main() {
  vec3 lightDirection = normalize(vec3(1, 2, -3));  // arbitrary light direction
  
  float l = dot(lightDirection, normalize(v_normal)) * .5 + .5;
  gl_FragColor = vec4(vec3(0,1,0) * l, 1);
}
`;

// compile shader, link, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);

// make some vertex data
const bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 1);

function render(time) {
  time *= 0.001;  // seconds
  
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);

  const fov = Math.PI * 0.25;
  const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
  const near = 0.1;
  const far = 100;
  const projection = toMat(perspective(fov, aspect, near, far));
  
  const camera = m4.translation([0, 0, 3]);
  const view = m4.inverse(camera);
  let modelView = m4.rotateY(view, time);

  gl.useProgram(programInfo.program);
  
  // calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  
  // calls gl.activeTexture, gl.bindTexture, gl.uniformXXX
  twgl.setUniforms(programInfo, {
    projection,
    modelView,
  });  
  
  // calls gl.drawArrays or gl.drawElements
  twgl.drawBufferInfo(gl, bufferInfo);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>

如果你想保持相同的视角数学(即使用来自矩阵glFrustum上面链接),那么这些都是你需要的值lrtb

  const t = near * Math.tan(0.5 * fov);
  const b = -t;
  const r = t * aspect;
  const l = -r;

'use strict';

/* global twgl, m4, requestAnimationFrame, document */

class Matrix4 { }

function perspective(fov, aspect, near, far) {

  const t = near * Math.tan(0.5 * fov);
  const b = -t;
  const r = t * aspect;
  const l = -r;
  
  const matrix = new Matrix4();
  matrix.n11 = (2 * near) / (r - l);
  matrix.n12 = 0;
  matrix.n13 = (r+l)/(r-l);
  matrix.n14 = 0;
  matrix.n21 = 0;
  matrix.n22 = (2 * near) / (t - b);
  matrix.n23 = (t+b)/(t-b);
  matrix.n24 = 0;
  matrix.n31 = 0;
  matrix.n32 = 0;
  matrix.n33 = (near + far) / (near - far);
  matrix.n34 = (2 * near * far) / (near - far);
  matrix.n41 = 0;
  matrix.n42 = 0;
  matrix.n43 = -1;
  matrix.n44 = 0;
  return matrix;
}

function toMat(m) {
  return [
    m.n11, m.n21, m.n31, m.n41,
    m.n12, m.n22, m.n32, m.n42,
    m.n13, m.n23, m.n33, m.n43,
    m.n14, m.n24, m.n34, m.n44,
  ];
}

const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl');

const vs = `
attribute vec4 position;
attribute vec3 normal;
attribute vec2 texcoord;

uniform mat4 projection;
uniform mat4 modelView;

varying vec3 v_normal;
varying vec2 v_texcoord;

void main() {
  gl_Position = projection * modelView * position;
  v_normal = mat3(modelView) * normal;
  v_texcoord = texcoord;
}
`;

const fs = `
precision highp float;

varying vec3 v_normal;
varying vec2 v_texcoord;
varying float v_modelId;

void main() {
  vec3 lightDirection = normalize(vec3(1, 2, -3));  // arbitrary light direction
  
  float l = dot(lightDirection, normalize(v_normal)) * .5 + .5;
  gl_FragColor = vec4(vec3(0,1,0) * l, 1);
}
`;

// compile shader, link, look up locations
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);

// make some vertex data
const bufferInfo = twgl.primitives.createCubeBufferInfo(gl, 1);

function render(time) {
  time *= 0.001;  // seconds
  
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.CULL_FACE);

  const fov = Math.PI * 0.25;
  const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
  const near = 0.1;
  const far = 100;
  const projection = toMat(perspective(fov, aspect, near, far));
  
  const camera = m4.translation([0, 0, 3]);
  const view = m4.inverse(camera);
  let modelView = m4.rotateY(view, time);

  gl.useProgram(programInfo.program);
  
  // calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  
  // calls gl.activeTexture, gl.bindTexture, gl.uniformXXX
  twgl.setUniforms(programInfo, {
    projection,
    modelView,
  });  
  
  // calls gl.drawArrays or gl.drawElements
  twgl.drawBufferInfo(gl, bufferInfo);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

动态渲染 Element 的 React Native 函数不会渲染任何内容

我的 useMemo useCallback 不会减少渲染次数。使用 useMemo 和 useCallback 的正确方法是什么?

释放GSL矩阵的正确方法是什么?

解决这个矩阵的正确方法是什么

在 Reactjs 中,在执行嵌套循环时不会渲染任何内容

在 blazor 中向数组增量添加内容而不重新渲染整个数组的正确方法是什么?

excel文件的正确内容类型是什么?

重置模式内容的正确方法是什么?

Javascript正确或错误测试不会输出任何内容

C中的Free()函数在释放重新分配的数据时不会产生任何错误,但不会释放实际内容。可能是什么原因?

在libgdx中渲染重复背景的正确方法是什么?

在Vulkan中实现“实例渲染”的正确方法是什么?

在React中渲染之前调用函数的正确位置是什么?

创建转换矩阵的numpy数组的正确方法是什么

计算用于目标检测的混淆矩阵的正确方法是什么?

将单个纹理的子集渲染到 WebGL 画布上的最快方法是什么?

Java jar文件的正确内容类型是什么?

从文件读取部分内容的正确方法是什么?

使用Bootstrap网格对齐内容的正确方法是什么?

在dockerfile所在目录中添加内容的正确方法是什么?

WebGL / Canvas中颜色正确的渲染

WebGL drawElements不绘制任何内容

“ onCreateView不会覆盖任何内容”

onCreateViewHolder不会覆盖任何内容

Choroplet不会绘制任何内容

'getView'不会覆盖任何内容

为什么 ReactDOM.render() 会渲染任何东西,但 ReactDOM.createRoot().render() 不会?

如果'grep'不返回任何内容,则分配给变量的内容是什么?

如何查找列表中是否有任何内容并确定“内容”是什么?