WebGL简介

WebGL简介

WebGL(全称为 Web Graphics Library)是一种基于浏览器的低级 3D 图形 API,允许开发者在网页中渲染复杂的交互式 2D 和 3D 图形,无需安装任何插件即可运行。它建立在 OpenGL ES 2.0 的基础上,并通过 JavaScript 接口操作 GPU 加速功能1。

发展历程

WebGL 的发展历程可以追溯至早期的跨平台图形接口需求。最初由 Khronos Group 提议并于 2011 年正式发布第一个版本 (WebGL 1.0),这标志着浏览器原生支持硬件加速图形处理的新纪元。随后,在 2017 年推出了 WebGL 2.0 版本,增加了更多高级特性如多重采样抗锯齿、着色器对象管理以及增强纹理格式的支持,进一步提升了性能和灵活性1。

随着互联网技术的进步及用户对沉浸式体验的要求不断提高,WebGL 成为了连接传统桌面应用程序与现代 web 应用之间的重要桥梁之一。特别是当 BabylonJS 这样的高层次库出现后,大大降低了使用难度并促进了其广泛应用领域的发展1。

当前现状

截至目前为止,几乎所有主流浏览器都已全面支持最新版的 WebGL 标准(即 WebGL 2.0 或更高) 。这意味着无论是在个人电脑还是移动设备上浏览含有复杂视觉效果的内容变得越来越普遍且流畅1。

此外值得注意的是,尽管存在其他新兴替代方案比如 WebGPU 正处于标准化过程中试图取代现有解决方案;但在未来几年内预计 WebGL 将继续作为主要工具被广泛采用特别是在需要良好兼容性的项目当中。

应用场景

游戏开发

利用 WebGL 可以制作高质量在线游戏,这些游戏可以直接嵌入网站页面之中供玩家即时游玩而不需要额外下载客户端软件。例如 Unity Technologies 提供了一种途径将他们的引擎产物导出成适合于 HTML5 环境下执行的形式,其中就包含了充分利用 WebGL 功能的部分。

数据可视化

除了娱乐用途之外,数据科学家们也越来越多地借助 WebGL 来呈现大规模多维度的数据集。因为它能够高效处理大量顶点坐标计算任务同时保持良好的帧率表现,所以非常适合用来构建动态图表或者地理信息系统(GIS)地图界面等等1。

``

`WebGL简单实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Rotating Cube</title>
    <style>body { margin: 0; } canvas { display: block; }</style>
</head>
<body>
    <canvas id="glcanvas" width="600" height="600"></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
    <script>
/* WebGL工具类 */
class WebGLUtils {
    static initShaderProgram(gl, vsSource, fsSource) {
        const vertexShader = this.loadShader(gl, gl.VERTEX_SHADER, vsSource);
        const fragmentShader = this.loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
        
        const shaderProgram = gl.createProgram();
        gl.attachShader(shaderProgram, vertexShader);
        gl.attachShader(shaderProgram, fragmentShader);
        gl.linkProgram(shaderProgram);

        if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
            alert('Shader program error: ' + gl.getProgramInfoLog(shaderProgram));
            return null;
        }
        return shaderProgram;
    }

    static loadShader(gl, type, source) {
        const shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            alert('Shader compile error: ' + gl.getShaderInfoLog(shader));
            gl.deleteShader(shader);
            return null;
        }
        return shader;
    }

    static initBuffer(gl, data) {
        const buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
        return buffer;
    }
}

/* 摄像机与投影类 */
class Camera {
    constructor(fov, aspect, near, far) {
        this.projectionMatrix = mat4.create();
        this.viewMatrix = mat4.create();
        mat4.perspective(this.projectionMatrix, fov, aspect, near, far);
        mat4.translate(this.viewMatrix, this.viewMatrix, [0, 0, -6]);
    }

    getProjectionMatrix() { return this.projectionMatrix; }
    getViewMatrix() { return this.viewMatrix; }

    update(deltaTime) {
        mat4.rotate(this.viewMatrix, this.viewMatrix, deltaTime * 0.5, [0, 1, 0]);
    }
}

/* 图形类 */
class Cube {
    constructor(gl, shaderProgram) {
        this.gl = gl;
        this.shaderProgram = shaderProgram;
        this.vertices = this.createCubeData();
        this.initBuffers();
    }

    createCubeData() {
        return [
            // 前面
            -1,-1,1, 1,0,0,1, 1,-1,1, 0,1,0,1, 1,1,1, 0,0,1,1, -1,1,1, 1,1,0,1,
            // 后面
            -1,-1,-1,1,0,1,1, 1,-1,-1,0,1,1,1, 1,1,-1,1,1,1,1, -1,1,-1,0.5,0.5,0.5,1,
            // 其他面数据...
        ];
    }

    initBuffers() {
        this.vertexBuffer = WebGLUtils.initBuffer(this.gl, this.vertices);
        
        const stride = 7 * Float32Array.BYTES_PER_ELEMENT;
        const positionLoc = this.gl.getAttribLocation(this.shaderProgram, 'aVertexPosition');
        this.gl.vertexAttribPointer(positionLoc, 3, this.gl.FLOAT, false, stride, 0);
        this.gl.enableVertexAttribArray(positionLoc);

        const colorLoc = this.gl.getAttribLocation(this.shaderProgram, 'aVertexColor');
        this.gl.vertexAttribPointer(colorLoc, 4, this.gl.FLOAT, false, stride, 3 * Float32Array.BYTES_PER_ELEMENT);
        this.gl.enableVertexAttribArray(colorLoc);
    }

    draw() {
        this.gl.drawArrays(this.gl.TRIANGLE_FAN, 0, 4);
        this.gl.drawArrays(this.gl.TRIANGLE_FAN, 4, 4);
        // 绘制其他面...
    }
}

/* 主程序 */
class Main {
    constructor() {
       
        this.canvas = document.getElementById('glcanvas');
        this.gl = this.canvas.getContext('webgl');
        this.initWebGL();
        this.camera = new Camera(
            45 * Math.PI/180,
            this.canvas.width/this.canvas.height,
            0.1,
            100
        );
        this.cube = new Cube(this.gl, this.shaderProgram);
        this.then = 0;
        this.render = this.render.bind(this);
        requestAnimationFrame(this.render);
    }

    initWebGL() {
        const vsSource = `
            attribute vec3 aVertexPosition;
            attribute vec4 aVertexColor;
            uniform mat4 uProjectionMatrix;
            uniform mat4 uViewMatrix;
            varying lowp vec4 vColor;
            void main() {
                gl_Position = uProjectionMatrix * uViewMatrix * vec4(aVertexPosition, 1.0);
                vColor = aVertexColor;
            }`;
        
        const fsSource = `
            precision lowp float;
            varying lowp vec4 vColor;
            void main() { gl_FragColor = vColor; }`;
        
        this.shaderProgram = WebGLUtils.initShaderProgram(this.gl, vsSource, fsSource);
        this.gl.useProgram(this.shaderProgram);
    }

    render(now) {
        now *= 0.001;
        const deltaTime = now - this.then;   
        this.then = now;
        this.camera.update(deltaTime);        
        this.gl.clearColor(0, 0, 0, 1);
        this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
        this.gl.enable(this.gl.DEPTH_TEST);
        
        const uProjection = this.gl.getUniformLocation(this.shaderProgram, 'uProjectionMatrix');
        const uView = this.gl.getUniformLocation(this.shaderProgram, 'uViewMatrix');
        this.gl.uniformMatrix4fv(uProjection, false, this.camera.getProjectionMatrix());
        this.gl.uniformMatrix4fv(uView, false, this.camera.getViewMatrix());

        this.cube.draw();
        requestAnimationFrame(this.render);
    }
}

// 启动程序
window.onload = () => new Main();
</script>
</body>
</html>

实例解释:

主程序类(main)

构造函数(constructor):
     1.  初始化画布(canvas)
     2. 初始化画笔(gl)
     3. 初始化调色板(initGL)
     4. 初始化 摄像机(Camera)
     5. 生成绘画对象(new Cube)
     6. 绑定渲染函数(render.bind(this))
     7. 其它初始化(then=0)
     8. 循环渲染(requestAnimationFrame)
GL初始化(initWebGL):
    1、 定义点着色器,片段着色器定义 
    2、绑定着色器(initShaderProgram)
    3、编译着色器(  useProgram)
图形渲染(render): 	
  1、初始化
  2、摄像机更新(Camera.update)
  3\   背景初始化
  4、投影矩阵变换
  5、绘制对象 
  6、循环渲染(requestAnimationFrame)

工具类(WebGLUtils)

着色器初始化
1、定义点着色器、片段着色器
2、定义着色程序
3、绑定点着色器、片段着色器
4、编译着色程序 
缓冲区初如化
1、创建缓冲区
2、绑定缓冲 区
3、装载缓冲数据
4、返回缓冲区

摄像机与投影类(camera)

构造函数(constructor)
1、创建投影、视图矩阵
2、生成带参投影、视图矩阵

图形类(Cube)

缓冲区初始化(initBuffer)
1、创建顶点缓冲 区
2、传递顶点数据至着色程序的aVertexPosition
3、传递颜色数据至着色程序的aVertexColor

绘制(draw)
绘制扇形: gl.drawArrays(this.gl.TRIANGLE_FAN, 0, 4);

此程序为WebGL的简单实例,实现简单图形 在三维空间进行旋转,其主要过程 模仿人的绘画 方式,先准备画布,笔(gl),调色板(initWebGL),绘制对象 、摄像机,再进行绘画 ,绘画 时按照清空背景,摄像机运动、绘制对象的顺序进行,进行循环渲染。

### WebGL 使用指南及示例代码 WebGL 是一种基于浏览器的图形渲染技术,允许开发者通过 JavaScript 在网页上绘制复杂的 2D 和 3D 图形。以下是关于 WebGL 的使用指南以及相关示例代码。 #### 1. WebGLShader 简介 WebGLShader 是 WebGL 中的核心组件之一,用于处理顶点和像素数据。通过编写顶点着色器(Vertex Shader)和片段着色器(Fragment Shader),可以实现高度定制化的渲染效果[^1]。顶点着色器负责处理几何数据,而片段着色器则负责计算每个像素的颜色。 #### 2. 创建和编译着色器 创建和编译着色器的过程包括以下几个关键步骤: - 定义顶点着色器和片段着色器的源代码。 - 将这些源代码传递给 WebGL 系统进行编译。 - 链接着色器程序以生成可执行的渲染逻辑。 以下是一个简单的顶点着色器和片段着色器的示例代码: ```javascript // 顶点着色器代码 const VSHADER_SOURCE = ` attribute vec4 a_Position; void main() { gl_Position = a_Position; } `; // 片段着色器代码 const FSHADER_SOURCE = ` void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 设置颜色为红色 } `; ``` #### 3. 初始化 WebGL 上下文 在使用 WebGL 进行渲染之前,需要初始化 WebGL 上下文并加载着色器程序。以下是一个完整的初始化过程: ```javascript function initWebGL(canvas) { const gl = canvas.getContext('webgl'); if (!gl) { console.error('无法获取 WebGL 上下文'); return null; } return gl; } function initShaders(gl, vshaderSource, fshaderSource) { const program = createProgram(gl, vshaderSource, fshaderSource); if (!program) { console.error('着色器初始化失败'); return false; } gl.useProgram(program); return true; } function createProgram(gl, vshaderSource, fshaderSource) { const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vshaderSource); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fshaderSource); if (!vertexShader || !fragmentShader) { return null; } const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error('无法链接着色器程序'); return null; } return program; } function loadShader(gl, type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error('着色器编译失败: ' + gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } ``` #### 4. 示例代码运行方法 为了运行上述代码,可以按照以下步骤操作: - 下载《WebGL编程指南》随书代码资源[^2]。 - 解压下载的 ZIP 文件到本地目录。 - 使用支持 WebGL 的现代浏览器打开相应的 HTML 文件。 - 查看和运行代码示例,了解其工作原理。 #### 5. 注意事项 - 确保使用的浏览器支持 WebGL 技术。如果某些代码示例无法正常运行,可能需要更新浏览器版本[^2]。 - 建议在运行代码前阅读《WebGL编程指南》的相关章节,以便更好地理解其实现原理。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值