当前位置: 首页 > news >正文

2、webgl 基本概念 + 绘制点

webGL 概念

webGL(Web图形库)是一种 JavaScript API,用于在任何兼容的 Web 浏览器中呈现交互式 3D 和 2D 图形

着色器语言

顶点着色器: 用来描述顶点特征的程序

// 一个属性值,将会从缓冲区中获取数据
attribute vec4 a_position;
// 所有着色器都有一个 main 方法
void main() {// gl_Position 是一个顶点着色器主要设置的变量gl_Position = a_position;
}

片元着色器: 进行逐片处理过程如光照的程序

void main() {
// 片元着色器中的内置变量gl_FragColor = vec4(0, 0, 0, 1);
}

变量声明

attribute 变量的声明
存储限定符 类型 变量名
attribute vec4 a_Position

着色器的变量声明方式——存储限定符

1、attribute 变量:传输的是与顶点有关的数据
2、uniform 变量: 传输的是对于所有顶点都相关(或与顶点无关)的数据(全局变量)
3、textures 变量:纹理(纹理是一个数据序列,可以在着色程序运行中随意读取其中的数据。大多数情况存放的是图像数据,但是纹理仅仅是数据序列,你也可以随意存放除了颜色数据以外的其它数据。)
4、Varing 可变变量: 可变量是一种顶点着色器给片元着色器传值的方式,依照渲染的图元是 点,线 还是三角形,顶点着色器中设置的可变量会在 片元着色器运行中获取不同的插值。

GLSL ES 数据类型

| 类别 | GLSL ES数据类型 | 描述 |
| 矢量 | vec2、vec3、vec4 | 具有 2/3/4 个浮点数元素的矢量 |
| | ivec2、ivec3、ivec4 | 具有 2/3/4 个整形元素的矢量 |
| | bvec2、bvec3、bvec4 | 具有 2/3/4 个布尔值元素的矢量|
| 矩阵 | mat2 、mat3、mat4 | 22、33、4*4 的浮点数元素的矩阵(分别具有4,9,16 个元素)|

核心内容

WebGL基本图形

只能绘制三种基本图元:点、线段、三角形
理解图元与复杂图形的关系

绘图上下文获取

通过canvas元素的getContext(‘webgl’)获取
需做浏览器兼容性判断

着色器系统

分为顶点着色器(处理顶点信息)和片元着色器(处理颜色)
两种着色器的分工与协作机制

GLSL变量声明

由存储限定符(attribute/uniform等)+数据类型+变量名组成
attribute与uniform的关键区别

坐标系统转换

WebGL采用归一化设备坐标(-1到1),需从canvas坐标转换
掌握坐标转换公式推导

着色器编程

必须赋值gl_Position内置变量,可选gl_PointSize
主函数必须声明返回类型(void)

动态绘制实现

通过鼠标事件获取坐标,使用vertexAttrib3f传值
顶点数据存储与批量绘制技巧

颜色随机生成

片元着色器通过gl_FragColor接收RGBA值(0-1范围)
精度声明precision mediump float的必要性

渲染管线流程

顶点着色器→图元装配→光栅化→片元着色器→帧缓冲区
理解各阶段数据传递过程

webgl 绘制点

绘制一个点

<!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" id="myCanvas"></canvas><script type="vertex" id="vertex">void main() {gl_Position = vec4(0, 0, 0, 1);gl_PointSize = 10.0;}</script><script type="fragment" id="fragment">void main() {gl_FragColor = vec4(1, 0, 0, 1);}</script><script>let myCanvas = document.getElementById("myCanvas");let gl = myCanvas.getContext("webgl");// IE8 之前的浏览器不兼容if(!gl) {alert("浏览器不支持 webgl!")}// 创建着色器function createShader(gl, type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);const isSuccess = gl.getShaderParameter(shader, gl.COMPILE_STATUS);return isSuccess ? shader : console.log(gl.getShaderInfoLog(shader))}function getInnerText(id) {return document.getElementById(id).innerText;}const vertexStr = getInnerText("vertex");const fragmentStr = getInnerText("fragment");const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexStr)const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentStr);function createProgram(gl, vertexShader, fragmentShader) {const program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);const isSuccess = gl.getProgramParameter(program, gl.LINK_STATUS);return isSuccess ? program : console.log(gl.getProgramInfoLog(program));}let program = createProgram(gl, vertexShader, fragmentShader);gl.useProgram(program);gl.clearColor(0, 0, 1, 1);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.POINT, 0, 1)</script>
</body>
</html>

根据鼠标点击位置绘制随机颜色的点

<!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" id="myCanvas"></canvas><script type="vertex" id="vertex">attribute vec2 a_position;attribute vec4 a_color;uniform vec2 screenSize;varying vec4 v_color;void main() {float x = a_position.x * 2.0 / screenSize.x - 1.0;float y = 1.0 - a_position.y * 2.0 / screenSize.y;gl_Position = vec4(x, y, 0, 1);gl_PointSize = 10.0;v_color = a_color;}</script><script type="fragment" id="fragment">precision mediump float;varying vec4 v_color;void main() {gl_FragColor = v_color;}</script><script>let myCanvas = document.getElementById("myCanvas");let gl = myCanvas.getContext("webgl");// IE8 之前的浏览器不兼容if(!gl) {alert("浏览器不支持 webgl!")}// 创建着色器function createShader(gl, type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);let isSuccess = gl.getShaderParameter(shader, gl.COMPILE_STATUS);return isSuccess ? shader : console.log(gl.getShaderInfoLog(shader))}function getInnerText(id) {return document.getElementById(id).innerText;}const vertexStr = getInnerText("vertex");const fragmentStr = getInnerText("fragment");const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexStr)const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentStr);// 创建程序function createProgram(gl, vertexShader, fragmentShader) {let program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);let isSuccess = gl.getProgramParameter(program, gl.LINK_STATUS);return isSuccess ? program : console.log(gl.getProgramInfoLog(program));}let program = createProgram(gl, vertexShader, fragmentShader);gl.useProgram(program);let a_position = gl.getAttribLocation(program, 'a_position');let screenSize = gl.getUniformLocation(program, 'screenSize');let a_color = gl.getAttribLocation(program, 'a_color');gl.uniform2f(screenSize, myCanvas.width, myCanvas.height);function bindEvent() {let points = [];myCanvas.onmousedown = e => {gl.clearColor(0, 0, 1, 1);gl.clear(gl.COLOR_BUFFER_BIT);let x = e.offsetX, y = e.offsetY;let color = randomColor();points.push({x,y,color})points.forEach(el => {let {r, g, b, a} = el.color;gl.vertexAttrib4f(a_color, r, g, b, a);gl.vertexAttrib3f(a_position, el.x, el.y, 0);gl.drawArrays(gl.POINT, 0, 1)})}}bindEvent()function randomColor() {let r = Math.random(), g = Math.random(), b = Math.random(), a = 0.5 + Math.random() * 0.5;return {r, g, b, a}}</script>
</body>
</html>

画布中随机位置绘制点

<!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" id="myCanvas"></canvas><script type="vertex" id="vertex">attribute vec2 a_position;attribute vec4 a_color;uniform vec2 screenSize;varying vec4 v_color;void main() {float x = a_position.x * 2.0 / screenSize.x - 1.0;float y = 1.0 - a_position.y * 2.0 / screenSize.y;gl_Position = vec4(x, y, 0, 1);gl_PointSize = 10.0;v_color = a_color;}</script><script type="fragment" id="fragment">precision mediump float;varying vec4 v_color;void main() {= v_color;}</script><script>let myCanvas = document.getElementById("myCanvas");let gl = myCanvas.getContext("webgl");// IE8 之前的浏览器不兼容if(!gl) {alert("浏览器不支持 webgl!")}// 创建着色器function createShader(gl, type, source) {const shader = gl.createShader(type);gl.shaderSource(shader, source);gl.compileShader(shader);let isSuccess = gl.getShaderParameter(shader, gl.COMPILE_STATUS);return isSuccess ? shader : console.log(gl.getShaderInfoLog(shader))}// 获取着色器中的文本内容字符串function getInnerText(id) {return document.getElementById(id).innerText;}const vertexStr = getInnerText("vertex");const fragmentStr = getInnerText("fragment");const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexStr)const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentStr);// 创建程序function createProgram(gl, vertexShader, fragmentShader) {let program = gl.createProgram();gl.attachShader(program, vertexShader);gl.attachShader(program, fragmentShader);gl.linkProgram(program);let isSuccess = gl.getProgramParameter(program, gl.LINK_STATUS);return isSuccess ? program : console.log(gl.getProgramInfoLog(program));}let program = createProgram(gl, vertexShader, fragmentShader);gl.useProgram(program);// 获取顶点着色器中变量let a_position = gl.getAttribLocation(program, 'a_position');let screenSize = gl.getUniformLocation(program, 'screenSize');let a_color = gl.getAttribLocation(program, 'a_color');// 获取画布的宽高,因为顶点着色器中已经gl.uniform2f(screenSize, myCanvas.width, myCanvas.height);function drawRandomPoint() {let el = {color: randomColor(),x: Math.random() * myCanvas.width,y: Math.random() * myCanvas.height}console.log(el)gl.clearColor(0, 0, 1, 1);gl.clear(gl.COLOR_BUFFER_BIT);let {r, g, b, a} = el.color;gl.vertexAttrib4f(a_color, r, g, b, a);gl.vertexAttrib3f(a_position, el.x, el.y, 0);gl.drawArrays(gl.POINT, 0, 1)}drawRandomPoint()// requestAnimationFrame(drawRandomPoint)// 绘制随机点setInterval(() => {drawRandomPoint()}, 1000);function randomColor() {let r = Math.random(), g = Math.random(), b = Math.random(), a = 0.5 + Math.random() * 0.5;return {r, g, b, a}}</script>
</body>
</html>
http://www.dtcms.com/a/558698.html

相关文章:

  • 重复打开同一个网站怎么做做网站广告软件
  • 高级系统架构师笔记——软件工程基础知识(3)逆向工程与需求工程
  • 山东网站建设seo软文推广广告公司
  • 精品成品网站入口网络推广计划书格式
  • 【Qt】 Qt5.14以下版本也可以使用 Q_TRACE_SCOPE啦 !!!
  • o2o网站建设怎么样北京市网站建设 维护推荐
  • 做平面设计在那个网站上找图好惠州做网站多少钱
  • Java接口规范升级 —— 给你的 Java 接口 “穿西装”(参数不瞎填,返回不乱码)
  • AI学习研究2025.11.1——deepseek-r1 1.5B 五轮问题下来暴露无法区别中英文
  • Dubbo 全解析:从入门到精通的分布式服务框架实战指南
  • 网站更改公司需要重新备案吗网站联盟怎么做
  • C与汇编深入分析
  • UDS中时间参数相关
  • 东莞网站制作建设项目之家
  • C++:链接的两难 —— ODR中的强与弱符号机制
  • 徐家汇网站建设秦皇岛海港区防疫人员事件
  • 长沙专业网站建设服务网站代备
  • 开始改变第七天 第一个面试
  • 网站资源做缓存做网站开发需要的笔记本配置
  • 搜索引擎网站盈利模式长沙旅游必去的八个景点
  • 如何写出让业务满意的性能测试报告?
  • 网站做数据分析整站优化seo平台
  • 烟台网站建设服务网站百度搜索不到
  • 做网站除了dw网站域名注册备案教程
  • 南华大学城市建设学院网站注册企业邮箱哪家最好
  • C++隐藏机制——extern 的边界:声明、定义与符号分配
  • 为什么选择做游戏网站做国外销售都上什么网站
  • C语言完成Socket通信
  • 关于Delphi的一次吵架的后续
  • 深圳网站制作公司兴田德润官网多少中企动力为什么留不住人