利用WebGL绘制简单几何

本文详细介绍了WebGL的基本概念,图形系统的绘图流程,特别是如何通过WebGLAPI在HTML5canvas上实现最简单的几何图形绘制,包括创建WebGL上下文、编写和链接着色器、设置缓冲区和执行渲染过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

利用WebGL绘制最简单的几何图形

一、WebGL简介

WebGL是一种用于在网页上渲染交互式3D和2D图形的JavaScript API。它基于OpenGL ES 2.0,提供了一种在浏览器中使用硬件加速图形的方式。

二、图形系统绘图流程

图形系统的通用绘图流程会包括六个部分:

  1. 输入设备
  2. 中央处理单元:首先,数据经过 CPU 处理,成为具有特定结构的几何信息。
  3. 图形处理单元:然后,这些信息会被送到 GPU 中进行处理。
  4. 存储器
  5. 帧缓存:光栅信息会输出到帧缓存中
  6. 输出设备

在这里插入图片描述

  1. 光栅(Raster):几乎所有的现代图形系统都是基于光栅来绘制图形的,光栅就是指构成图像的像素阵列。
  2. 像素(Pixel):一个像素对应图像上的一个点,它通常保存图像上的某个具体位置的颜色等信息。
  3. 帧缓存(Frame Buffer):在绘图过程中,像素信息被存放于帧缓存中,帧缓存是一块内存地址。
  4. CPU(Central Processing Unit):中央处理单元,负责逻辑计算。
  5. GPU(Graphics Processing Unit):图形处理单元,负责图形计算。

三、渲染管线

渲染管线(Rendering Pipeline)是指计算机图形学中用于生成图像的一系列阶段和处理步骤。它描述了从输入几何数据到最终呈现图像的整个过程。渲染管线通常包括以下几个主要阶段:

  1. 应用阶段(Application Stage):在这个阶段,程序接收输入数据,例如顶点数据、纹理信息等。这些数据通常由应用程序提供,例如游戏引擎或者图形应用。
  2. 几何处理阶段(Geometry Processing Stage):在这个阶段,输入的几何数据(例如顶点、线段、三角形等)经过一系列变换(如模型变换、视图变换、投影变换等)和剪裁(Clipping),最终形成裁剪后的几何图形。
  3. 光栅化阶段(Rasterization Stage):在这个阶段,几何图形被转换为像素的集合,即光栅化。光栅化的过程包括确定每个像素的位置和颜色,以及应用纹理映射等操作。
  4. 片段处理阶段(Fragment Processing Stage):在这个阶段,对光栅化后的像素进行处理,计算最终的颜色值。这包括应用光照模型、纹理采样、深度测试、融合操作等。
  5. 输出阶段(Output Stage):最终生成的像素数据被发送到图形硬件的输出缓冲区,呈现在屏幕上。

在这里插入图片描述

四、WebGL绘图流程

1、创建获取WebGL上下文
const gl = document.querySelector("canvas").getContext("webgl");
2、创建WebGL程序(WebGL Program)
  1. 编写着色器

       //顶点着色器
        const vertex = `
        attribute vec2 position;
    
        void main(){
            gl_PointSize = 1.0;
            gl_Position = vec4(position,0.0,1.0);
        }
        `;
        // 片元着色器
        const fragment = `
        precision mediump float;
        void main(){
            gl_FragColor = vec4(1.0,0.0,0.0,1.0);
        }
        `;
    
  2. 创建shader对象

        //创建顶点着色器
        const vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, vertex);
        gl.compileShader(vertexShader);
    
        //创建片元着色器
        const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, fragment);
        gl.compileShader(fragmentShader);
    
  3. 创建WebGLProgram对象

        //创建WebGLPrgame对象
        const program = gl.createProgram();
        gl.attachShader(program, vertexShader);
        gl.attachShader(program, fragmentShader);
    
  4. 连接并启用WebGLProgram对象

        gl.linkProgram(program);
        gl.useProgram(program); //启用webglProgram对象
    
3、将数据存入缓冲区
  1. 创建一个缓存对象

        const triangle = new Float32Array([-1, -1, 0, 1, 1, -1]);
        const bufferId = gl.createBuffer();
    
  2. 绑定为当前操作对象

        gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
    
  3. 当前数据写入缓存对象

        gl.bufferData(gl.ARRAY_BUFFER, triangle, gl.STATIC_DRAW);
    
4、将缓冲区数据读取到GPU
    //获取顶点着色器的position的变量位置下标
    const vPosition = gl.getAttribLocation(program, "position");
    gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);//从bindBuffer绑定的缓冲区中读取数据
    gl.enableVertexAttribArray(vPosition);//激活这个变量
5、GPU执行WebGL程序,输出结果
    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, triangle.length / 2);

五、完整代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <canvas width="500" height="500"></canvas>
  </body>
  <script type="module">
    const gl = document.querySelector("canvas").getContext("webgl");
    //顶点着色器
    const vertex = `
    attribute vec2 position;

    void main(){
        gl_PointSize = 1.0;
        gl_Position = vec4(position,0.0,1.0);
    }
    `;
    // 片元着色器
    const fragment = `
    precision mediump float;
    void main(){
        gl_FragColor = vec4(1.0,0.0,0.0,1.0);
    }
    `;

    //创建顶点着色器
    const vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, vertex);
    gl.compileShader(vertexShader);

    //创建片元着色器
    const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, fragment);
    gl.compileShader(fragmentShader);

    //创建WebGLPrgame对象
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program); //启用webglProgram对象

    //创建一个三角形坐标数据,并存入缓冲区
    const triangle = new Float32Array([-1, -1, 0, 1, 1, -1]);
    const bufferId = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, bufferId);
    gl.bufferData(gl.ARRAY_BUFFER, triangle, gl.STATIC_DRAW);

    //获取顶点着色器的position的变量位置下标
    const vPosition = gl.getAttribLocation(program, "position");
    gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);//从bindBuffer绑定的缓冲区中读取数据
    gl.enableVertexAttribArray(vPosition);//激活这个变量

    gl.clear(gl.COLOR_BUFFER_BIT);
    gl.drawArrays(gl.TRIANGLES, 0, triangle.length / 2);
  </script>
</html>

六、顶点着色器向片元着色器传值

    // 顶点着色器
    const vertex = `
    attribute vec2 position;
    varying vec3 color;

    void main(){
        gl_PointSize = 1.0;
        color = vec3(0.5 + position * 0.5 , 0.0);
        gl_Position = vec4(position*0.5,1.0,1.0);
    }`;

    // 片元着色器
    const fragment = `
    precision mediump float;
    varying vec3 color;
    void main(){
        gl_FragColor = vec4(color,1.0);
    }`;

在这里插入图片描述

<think>好的,用户想了解如何使用WebGL绘制圆柱体,并且需要示例。首先,我需要回忆WebGL的基本绘制流程,通常包括初始化着色器、创建缓冲区、定义顶点数据、设置投影和视图矩阵等步骤。 圆柱体可以分解为顶部、底部和侧面。顶部和底部是圆形,可以用三角形扇形来绘制,而侧面则可以用三角形带或者多个矩形面片拼接。不过,侧面更常见的是用多个矩形面片来近似圆柱体的曲面,这样可以通过增加分段数来提高精度。 接下来需要考虑顶点数据的生成。对于顶部和底部,需要计算圆周上的点坐标,通常使用极坐标公式:$x = r \cos(\theta)$, $y = r \sin(\theta)$,其中$\theta$从0到$2\pi$分多个步骤。每个圆的中心点也需要作为顶点。 侧面的顶点则需要将顶部和底部的对应点连接起来,形成矩形面片。每个面片由两个三角形组成,或者使用三角形带减少顶点数量。这里需要注意的是法线的计算,因为光照效果需要正确的法线信息。侧面的法线应该垂直于圆柱体的表面,即从中心轴向外辐射的方向。 然后是着色器的编写。顶点着色器需要处理顶点位置、法线,并将它们转换到视图空间。片段着色器则根据光照模型计算颜色,可能需要使用Phong或Blinn-Phong光照模型。 用户提供的示例代码中已经有一个基础的WebGL程序结构,但需要调整顶点生成部分来适应圆柱体。需要生成顶部、底部和侧面的顶点数据,并为每个顶点分配正确的法线。此外,索引缓冲区可能需要调整,以正确连接各个三角形。 可能遇到的问题包括顶点顺序导致的背面剔除问题,需要确保顶点顺序是逆时针的。另外,法线计算错误会导致光照不自然,需要仔细验证法线方向。 最后,需要验证代码的正确性,可能通过逐步调试或在简单场景中测试圆柱体的渲染效果,确保顶点和法线数据正确无误。</think>使用WebGL绘制圆柱体需要分解几何结构为可渲染的三角形,以下是分步实现方法: 一、几何建模原理 圆柱体由三个部分组成: 1. 顶部圆形:半径$r$,中心点$(0,h,0)$ 2. 底部圆形:半径$r$,中心点$(0,0,0)$ 3. 侧面:高度$h$,由多个矩形面片组成 顶点坐标计算公式: $$x = r \cdot \cos\theta$$ $$z = r \cdot \sin\theta$$ 其中$\theta$在$[0, 2\pi]$区间内等分 二、完整实现代码示例 ```javascript // 创建圆柱体顶点数据 function createCylinder(radius=1, height=2, segments=32) { const positions = []; const normals = []; const indices = []; // 生成顶部和底部顶点 for(let y = 0; y <= height; y += height) { const center = [0, y, 0]; positions.push(...center); normals.push(0, y >
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值