WebGL中3D数学基础

目录


在WebGL中,3D数学是不可或缺的一部分,因为它涉及到了几何、变换和着色的计算。以下是3D数学基础的一些关键概念以及在WebGL中的应用:

坐标系统:

右手坐标系统:WebGL使用右手坐标系统,其中X轴正方向指向右,Y轴正方向向上,Z轴正方向从屏幕向外(通常是显示器的后方)。

向量(Vector):

向量表示方向和大小,通常以数组形式表示,如[x, y, z]。在WebGL中,向量用于表示位置、速度、颜色等。

矩阵(Matrix):

矩阵用于描述变换,如平移、旋转和缩放。在WebGL中,我们通常使用4x4的矩阵,因为它们可以同时处理位置和变换。

平移(Translation):

平移矩阵可以通过将原点平移到新的位置来创建。例如,平移向量[tx, ty, tz]的矩阵是:

     var translateMatrix = mat4.create();
     mat4.translate(translateMatrix, translateMatrix, [tx, ty, tz]);

旋转(Rotation):

旋转可以通过绕某个轴进行。例如,绕X轴旋转angle度的矩阵是:

     var rotateXMatrix = mat4.create();
     mat4.rotateX(rotateXMatrix, rotateXMatrix, angle);

对于绕Y轴和Z轴的旋转,有mat4.rotateY()和mat4.rotateZ()。

缩放(Scaling):

缩放矩阵可以沿每个轴独立缩放。例如,缩放因子[sx, sy, sz]的矩阵是:

     var scaleMatrix = mat4.create();
     mat4.scale(scaleMatrix, scaleMatrix, [sx, sy, sz]);

组合变换:

可以通过矩阵乘法组合多个变换。例如,先平移再旋转:

     var transformationMatrix = mat4.create();
     mat4.multiply(transformationMatrix, translateMatrix, rotateXMatrix);

顶点着色器中的变换:

在顶点着色器中,我们通常将模型空间中的顶点坐标通过模型视图投影矩阵(model-view-projection matrix, MVP)转换到裁剪空间:

     attribute vec3 a_position;
     
     uniform mat4 u_modelMatrix;
     uniform mat4 u_viewMatrix;
     uniform mat4 u_projectionMatrix;
     
     void main() {
       gl_Position = u_projectionMatrix * u_viewMatrix * u_modelMatrix * vec4(a_position, 1.0);
     }

矩阵堆栈:

在实际应用中,为了方便管理变换,通常会使用矩阵堆栈(例如,mat4.perspective()mat4.lookAt()等),它们可以帮助你更简洁地组织和回滚变换。

向量和矩阵操作库:

在JavaScript中,可以使用gl-matrix这样的库来处理3D数学。例如,上述代码中的mat4.create()mat4.translate()等都是gl-matrix库的方法。

法线(Normals):

法线向量表示表面的切线方向,用于计算光照。在WebGL中,我们需要将法线从模型空间转换到视图空间,以便正确地计算光照。在顶点着色器中,这通常如下所示:

      attribute vec3 a_normal;
      
      varying vec3 v_normal;
      
      uniform mat4 u_normalMatrix;
      
      void main() {
        v_normal = normalize(mat3(u_normalMatrix) * a_normal);
        
        // ...其他变换...
      }
  • 注意,法线矩阵(u_normalMatrix)通常是模型视图矩阵的逆转置,以保持法线的方向。

纹理坐标(Texture Coordinates):

  • 纹理坐标用于将2D纹理映射到3D模型的表面。在顶点着色器中,我们需要将纹理坐标传递给片段着色器:
      attribute vec2 a_texCoord;
      
      varying vec2 v_texCoord;
      
      void main() {
        // ...其他变换...
        
        v_texCoord = a_texCoord;
      }
  • 在片段着色器中,我们可以使用纹理坐标来采样纹理:
      uniform sampler2D u_texture;
      
      varying vec2 v_texCoord;
      
      void main() {
        gl_FragColor = texture2D(u_texture, v_texCoord);
      }

视口变换:

视口变换将裁剪空间的坐标转换为屏幕空间。这是通过gl.viewport()函数完成的,它设置了WebGL渲染的目标区域。

深度测试(Depth Testing):

深度测试用于确定哪些像素应该覆盖其他像素。WebGL默认开启深度测试,你可以通过gl.enable(gl.DEPTH_TEST)启用或禁用它。

混合(Blending):

混合允许你将新绘制的颜色与现有颜色混合,创建透明效果。这通常在绘制具有alpha通道的纹理时使用:

      gl.enable(gl.BLEND);
      gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

深度缓冲(Depth Buffer):

深度缓冲用于存储每个像素的深度值,用于深度测试。WebGL默认创建了深度缓冲,但你可以检查并配置它:

      gl.clearDepth(1.0);
      gl.clear(gl.DEPTH_BUFFER_BIT);

裁剪(Clipping):

裁剪用于限制渲染的区域。你可以使用gl.enable(gl.SCISSOR_TEST)gl.scissor()来设置裁剪区域。

视口变换(Viewport Transform):

视口变换将裁剪空间的坐标映射到设备像素。默认情况下,这由WebGL自动处理,但你可以通过gl.viewport()自定义。

投影(Projection):

投影用于将3D空间中的点转换为2D屏幕空间。在WebGL中,常见的投影类型有透视投影和正交投影。透视投影用于模拟人的远近感知,而正交投影则用于创建等比例缩放的2D视图。
透视投影通常用于3D场景,使用mat4.perspective()生成:

     var fieldOfView = 45 * Math.PI / 180; // 45度
     var aspect = canvas.width / canvas.height; // 布局宽高比
     var near = 0.1; // 近裁剪平面
     var far = 100; // 远裁剪平面
     var projectionMatrix = mat4.create();
     mat4.perspective(projectionMatrix, fieldOfView, aspect, near, far);

正交投影用于2D场景或等比例缩放的3D场景,使用mat4.ortho()生成:

     var left = -1; // 左边界
     var right = 1; // 右边界
     var bottom = -1; // 下边界
     var top = 1; // 上边界
     var near = -1; // 近裁剪平面
     var far = 1; // 远裁剪平面
     var orthoMatrix = mat4.create();
     mat4.ortho(orthoMatrix, left, right, bottom, top, near, far);

视锥体剔除(Frustum Culling):

视锥体剔除是一种优化技术,用于避免渲染超出视锥体的几何体。WebGL的深度测试已经包含了一些基本的视锥体剔除,但你也可以手动检查每个物体是否在视锥体内。

剔除(Culling):

剔除是另一种优化技术,用于避免渲染不可见的面。WebGL支持背面剔除(back-face culling),它默认开启,可以检查每个面的法线是否面向观察者。

顶点缓冲对象(Vertex Buffer Objects, VBOs):

顶点缓冲对象用于存储顶点数据,可以提高性能,减少内存拷贝。使用gl.bindBuffer()和gl.bufferData()创建和绑定VBO:

      var vertices = ... // 顶点数据
      var vertexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

索引缓冲对象(Element Array Buffers, EBOs):

索引缓冲对象用于指定顶点的顺序,从而创建多边形。使用gl.bindBuffer()和gl.bufferData()创建和绑定EBO:

      var indices = ... // 索引数据
      var indexBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

纹理单元(Texture Units):

WebGL支持多个纹理单元,可以同时应用多个纹理。使用gl.activeTexture()gl.uniform1i()切换和设置纹理单元:

      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, texture1);
      gl.uniform1i(shader.uniforms.u_texture1, 0);

      gl.activeTexture(gl.TEXTURE1);
      gl.bindTexture(gl.TEXTURE_2D, texture2);
      gl.uniform1i(shader.uniforms.u_texture2, 1);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天涯学馆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值