原生webgl学习(二) 用WebGL绘制一个三角形

这篇博客介绍了如何使用WebGL从头开始绘制一个带有颜色的三角形。文章首先强调了了解着色器的重要性,然后通过创建HTML文档、设置canvas、引入相关脚本以及编写着色器代码来逐步展示绘制过程。主要步骤包括获取canvas元素,检查WebGL支持,编译和链接着色器,定位attribute变量,创建缓冲区并绑定数据,最后调用gl.drawArrays进行绘制。示例代码可在作者的gitee码云上找到,后续章节将深入探讨矩阵运算。

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

所有示例代码均可在我的gitee码云上,读者可自行下载:https://gitee.com/babyogl/learnWebGL,本文示例代码在chapter-01里面,引用文件都在libs文件夹下;为了让读者不至于枯燥乏味,这一篇文章我们不讲计算和理论,相关的矩阵运算和理论留在后面,现在只是单纯的介绍WebGL一些接口和用法,从一个简单的示例开始:绘制一个带颜色的三角形。

在开始之前,需要知道着色器的相关知识,可以参考:webgl介绍里面的着色器介绍,本文的demo 用到的着色器为:

    <script id="vertex-shader" type="x-shader/x-vertex">
        attribute vec4 a_position;
        void main() {
            gl_Position = a_position;
        }
    </script>

    <script id="fragment-shader" type="x-shader/x-fragment">
        precision mediump float;//将精度设置为中等精度
        void main() {
            gl_FragColor = vec4(1, 0, 0.5, 1);
        }
    </script>

其中的attribute定义了一个vec4四维变量,用于表示每个顶点的位置信息,gl_Position代表顶点的位置, a_position是着色器用于接收来自JavaScript代码的顶点位置信息的入口。gl_FragColor代表每个片元的颜色,通俗的理解是用于设置顶点

HTML5中的WebGL是一种基于OpenGL ES的JavaScript API,它可以在浏览器上创建交互式的3D图形。要在原生WebGL画布上从(0,0)点开始绘制图片,你需要通过创建纹理并将其绑定到合适的顶点数组对象(VAO),然后设置相应的着色器程序。 以下是一个简单的WebGL Demo,用于在WebGL画布上从(0,0)绘制图片: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>WebGL Image Draw</title> <style> body { margin: 0; } canvas { display: block; width: 100%; height: 100%;} </style> </head> <body> <canvas id="glCanvas" width="640" height="480"></canvas> <script> // 创建 WebGL 上下文 const canvas = document.getElementById('glCanvas'); const gl = canvas.getContext('webgl'); if (!gl) { console.error("Your browser does not support WebGL."); return; } // 加载图片 let image = new Image(); image.src = 'path_to_your_image.jpg'; // 替换为你图片的实际路径 image.onload = function() { // 设置纹理 const texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); // 将图片位置设置为(0, 0) const vertices = [ -1, -1, 1, -1, -1, 1, 1, 1 ]; const uvCoordinates = [ 0, 0, 1, 0, 0, 1, 1, 1 ]; // 创建VAO、VBO const vao = gl.createVertexArrayObject(); gl.bindVertexArray(vao); const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); const uvBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(uvCoordinates), gl.STATIC_DRAW); // 定义顶点着色器 const vertexShaderSource = ` attribute vec2 a_position; attribute vec2 a_texCoord; varying vec2 v_texCoord; void main() { gl_Position = vec4(a_position * 0.5 + 0.5, 0.0, 1.0); v_texCoord = a_texCoord; } `; const vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vertexShaderSource); gl.compileShader(vertexShader); // 定义片段着色器 const fragmentShaderSource = ` precision mediump float; uniform sampler2D u_texture; varying vec2 v_texCoord; void main() { gl_FragColor = texture2D(u_texture, v_texCoord); } `; const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, fragmentShaderSource); gl.compileShader(fragmentShader); // 绑定着色器 const shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); gl.useProgram(shaderProgram); // 绑定纹理和顶点数据 gl.uniform1i(gl.getUniformLocation(shaderProgram, "u_texture"), 0); // 第0个纹理单位 gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.vertexAttribPointer(gl.getAttribLocation(shaderProgram, "a_position"), 2, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer); gl.vertexAttribPointer(gl.getAttribLocation(shaderProgram, "a_texCoord"), 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, "a_position")); gl.enableVertexAttribArray(gl.getAttribLocation(shaderProgram, "a_texCoord")); // 渲染循环 requestAnimationFrame(drawScene); }; function drawScene() { gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); requestAnimationFrame(drawScene); } </script> </body> </html> ``` 在这个示例中,当图片加载完成后,我们创建了一个纹理,并将其应用到一个三角形贴图上,使其覆盖整个画布。记得将`image.src`替换为你的图片URL。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值