webgl入门-基础三角形绘制

news2024/11/26 19:28:58

背景

最近工作上频繁接触webgl,因为不熟悉每每看到shader中的语法总感觉脑袋大,所以打算开始从零学习一下webgl,文章只做记录学习历程,那就直接开始吧!

开始

可以配合着这个文章食用。

我还是对webgl有一些概念的,说一下我的理解就是用来对图元进行光栅化的程序,首先说光栅化是什么,我的理解是将看到的东西画到屏幕上,那这个过程会经历什么比如画一个三角形,首先我要确定三角形画在哪里也就是顶点的位置,然后确认顶点后填充颜色,颜色其实就是一个个像素组成的,gpu做的就是将一个个gpu渲染上颜色这个过程叫光栅化。
ok,总结一下,一个webgl着色器程序,它需要有两部分组成:

  1. 顶点着色器(VertexShader)
  2. 片元着色器(FragmentShader)

好,以上两个着色器即可组成一个着色器程序。

代码实践

着色器创建流程

  1. 首先获取webgl的上下文
  2. 编写顶点和片元着色器代码
  3. 实例创建顶点和片元shader
  4. 创建着色器程序Program,并注入两个shader

下面代码不包含glsl代码

function initWebgl() {
    const canvas = document.getElementById('canvas');
    const gl = canvas.getContext('webgl');
    // 平面空间大小
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
    // 清空画布
    gl.clearColor(0, 0, 0, 0);
    gl.clear(gl.COLOR_BUFFER_BIT);

    return gl;
}
const gl = initWebgl();

// 创建着色器方法,输入参数:渲染上下文,着色器类型,数据源
function createShader(gl, type, source) {
    const shader = gl.createShader(type); // 创建着色器对象
    gl.shaderSource(shader, source); // 提供数据源
    gl.compileShader(shader); // 编译 -> 生成着色器
    const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
    if (success) {
        return shader;
    }

    console.log(gl.getShaderInfoLog(shader));
    gl.deleteShader(shader);
}

const vertexShaderSource = document.querySelector('#vertex-shader-2d').text;
const fragmentShaderSource = document.querySelector('#fragment-shader-2d').text;

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

// 创建着色器程序
function createProgram(gl, vertexShader, fragmentShader) {
    const program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);
    const success = gl.getProgramParameter(program, gl.LINK_STATUS);
    if (success) {
        return program;
    }

    console.log(gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
}

// 着色器创建成功
const program = createProgram(gl, vertexShader, fragmentShader);

至此准备工作已做好

数据传递流程

现在我想画一个三角形就需要用到顶点着色器,传递给它三个顶点的位置

  1. 首先先寻找要赋值的顶点着色器变量
  2. 创建一个缓冲区
  3. 再创建一个buffer,绑定在缓冲区中
  4. 将数据写入buffer
  5. enableVertexAttribArray:开启属性,这时变量和缓冲区建立好链接了
  6. vertexAttribPointer:规定数据如何读取

代码体现

// 找出顶点着色器中a_position变量
// 这要注意:寻找属性值位置(和全局属性位置)应该在初始化的时候完成,而不是在渲染循环中。
const positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
// 创建一个缓冲
const positionBuffer = gl.createBuffer();

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// 三个顶点坐标
const positions = [0, 0, 0, 0.5, 0.7, 0];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

// 告诉gl是用那个着色器程序
gl.useProgram(program);

// 启用属性
gl.enableVertexAttribArray(positionAttributeLocation);

// 告诉属性怎么从positionBuffer中读取数据 (ARRAY_BUFFER)
const size = 2; // 每次迭代运行提取两个单位数据
const type = gl.FLOAT; // 每个单位的数据类型是32位浮点型
const normalize = false; // 不需要归一化数据
const stride = 0; // 0 = 移动单位数量 * 每个单位占用内存(sizeof(type))
// 每次迭代运行运动多少内存到下一个数据开始点
const offset = 0; // 从缓冲起始位置开始读取
gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);

附一些语法规则定义:
请添加图片描述
请添加图片描述

请添加图片描述

开始绘制

需要制定绘制规则,因为gl不知道你是要画三个点还是一个三角形,还有程序执行次数。

代码体现

// 设置图元类型为三角形
const primitiveType = gl.TRIANGLES;
const drawArraysOffset = 0;
// 程序执行次数
const count = 3;
gl.drawArrays(primitiveType, drawArraysOffset, count);

在顶点绘制完成后,gl能够知道哪些像素是需要通过片元着色器进行上色的,至此基础的三角形绘制完毕!

ok,总结一下

一个基础的着色器程序主要流程是:

  1. 创建webgl上下文
  2. 创建顶点着色器和片元着色器组成一个完整的着色器程序
  3. 数据传递,今天的demo只进行了顶点数据传递
  4. 执行着色器程序(可配置执行规则)

本人对数据传递有些模糊,特画了个流程图清晰一下

请添加图片描述

附文章:
https://webglfundamentals.org/webgl/lessons/zh_cn/webgl-fundamentals.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1160849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云备份|| 日志 day2】FileUtil JsonUtil

这几天感冒了,稍微落下了进度 util工具 fileUtil(文件操作类) 在客户端,又或者是在服务端,本质是都是对文件的读写和管理,所以有必要封装一个文件操作类。 class FileUtil{ private:std::string _name; …

Unity Editor工具,导出unitypackage可选择是否包含脚本

概述 Unity自带的Export Package...功能,如果选中资源中包含脚本,或者Prefab挂载了自定义的脚本。在之后弹出的选择框内,如果勾选了Include dependencies会将整个项目所有的脚本全部都包含在内。等于导入了很多不相关的代码。如果取消勾选In…

Express框架开发接口之req.params、req.query与req.body的区别

1.req.query 用于get请求 http://localhost:3000/user?usernameljz&age1 获取 URL 中携带的查询参数 通过req.query对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数: 2.req.params 用于get请求 url路径为&#xff…

Ubuntu MySQL客户端功能介绍(mysql-client)mysql命令(mysql客户端命令)数据库导出、数据库导入

文章目录 Ubuntu MySQL客户端(mysql-client)功能介绍MySQL客户端与服务端服务器端(MySQL Server)客户端(MySQL Client) 安装MySQL客户端连接到MySQL服务器(mysql -h host -u user -p)执行SQL查询批处理模式…

SpringCloud-Alibaba-Seata

SpringCloud-Alibaba-Seata 注意:最好使用JDK1.8,使用JDK17整合seata会出现一些问题!!! Docker部署Seata1.5.2 1:拉取Seata1.5.2镜像: docker pull seataio/seata-server:1.5.22:在…

C/C++奇数求和 2021年3月电子学会青少年软件编程(C/C++)等级考试一级真题答案解析

目录 C/C奇数求和 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 C/C奇数求和 2021年3月 C/C编程等级考试一级编程题 一、题目要求 1、编程实现 计算非负整数 m 到 n(包括m 和 n &#xff…

驱动开发11-2 编写SPI驱动程序-点亮数码管

驱动程序 #include <linux/init.h> #include <linux/module.h> #include <linux/spi/spi.h>int m74hc595_probe(struct spi_device *spi) {printk("%s:%d\n",__FILE__,__LINE__);char buf[]{0XF,0X6D};spi_write(spi,buf,sizeof(buf));return 0; …

HNU-数据库系统-讨论课1

第一次小班讨论课安排如下: 主题: 大数据管理及前沿技术讨论 目的&#xff1a;让学生了解大数据管理的相关理论、技术和系统。 内容: &#xff08;1&#xff09;大数据概念、应用、技术的相关知识。 &#xff08;2&#xff09;AI4DB &#xff08;3&#xff09;DB4AI &…

代码随想录打卡第五十八天|● 583. 两个字符串的删除操作 ● 72. 编辑距离

583. 两个字符串的删除操作 题目&#xff1a; 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 题目链接&#xff1a; 583. 两个字符串的删除操作 解题思路&#xff1a; dp数组的含义&am…

基于springboot漫画动漫网站

基于springbootvue漫画动漫网站 摘要 基于Spring Boot的漫画动漫网站是一个精彩的项目&#xff0c;它结合了现代Web开发技术和漫画爱好者的热情。这个网站的目标是为用户提供一个便捷的平台&#xff0c;让他们能够欣赏各种漫画和动漫作品&#xff0c;与其他爱好者分享他们的兴趣…

Linux启动故障排错

Linux启动过程 开机流程、模块管理-CSDN博客 Grub三个阶段 1st stage&#xff1a;执行Grub主程序。Grub安装在MBR。由于MBR太小&#xff0c;所以与配置文件分开放1.5 stage&#xff1a;识别不同的文件系统2nd stage&#xff1a;加载Grub配置文件 /boot/grub2/grub.cfg。配置…

wordpress上传限制2M修改为256M的两种方式

方式一&#xff1a;修改php.ini 上传文件限制大小主要是php的php.ini配置决定的&#xff0c;所以只要找到php的配置文件&#xff0c;并且修改里面的配置即可&#xff0c;linux查看php的版本和配置文件位置的命令&#xff1a; php -i | grep "Configuration File" 一…

PTA 函数题(C语言)-- 阶乘计算升级版

题目title&#xff1a; 阶乘计算升级版 题目作者&#xff1a; 陈越 浙江大学 本题要求实现一个打印非负整数阶乘的函数。 函数接口定义&#xff1a; void Print_Factorial ( const int N ); 其中N是用户传入的参数&#xff0c;其值不超过1000。如果N是非负整数&#…

操作系统:文件管理(一)文件系统基础

一战成硕 4.1 文件系统基础4.1.1 文件的基本概念4.1.2 文件控制块和索引结点4.1.3 文件的操作4.1.4 文件保护4.1.5 文件的逻辑结构4.1.6 文件的物理结构 4.1 文件系统基础 4.1.1 文件的基本概念 文件是以硬盘为载体的存储在计算机上的信息的结合。 在系统运行时&#xff0c;计…

用rust写web服务器笔记(11/1)

文章目录 一、创建一个具有监听链接功能web服务器二、读取请求内容三、编写web服务器返回网页(编写响应)四、编写web服务器有条件的返回网页五、编写多线程的web服务器六、用线程池实现web服务器七、实现线程池清除的web服务器八、读取文件 rust官网文档地址&#xff1a;https:…

传音影像团队图像超分辨领域的论文被国际计算机视觉顶级会议ICCV 2023录用

近日&#xff0c;国际计算机视觉大会 ICCV 2023&#xff08;International Conference on Computer Vision&#xff0c;简称ICCV&#xff09;在法国巴黎召开。传音影像团队与哈尔滨工业大学机器学习研究中心合作完成的图像超分辨领域的论文“MetaF2N: Blind Image Super-Resolu…

10个免费的设计素材网站分享,高效设计不是梦!

今天&#xff0c;我想和大家分享10个新的优秀设计资源网站&#xff0c;包括免费设计素材站、设计工具、字体等网站&#xff0c;特别是一些素材网站&#xff0c;都是免费下载的。而且相对来说&#xff0c;他们提供的设计素材的风格都是目前比较流行的&#xff0c;非常适合我们追…

Linux | 如何保持 SSH 会话处于活动状态

在远程服务器管理和安全数据传输中&#xff0c;SSH&#xff08;Secure Shell&#xff09;是不可或缺的工具。然而&#xff0c;它的便利性和安全性有时会因常见的问题而受到损害&#xff1a;冻结 SSH 会话。 此外&#xff0c;session 的突然中断可能会导致工作丢失、项目延迟和无…

uniapp开发小程序无法上传图片的解决方法

登录小程序后台&#xff0c;第一步菜单栏 设置 第二步&#xff0c;用户隐私保护 更新 第三步 选2 第四步 勾选需要的接口&#xff0c;并说明 等审核通过后&#xff0c;一会就能正常上传图片。

深度学习之基于YoloV5火灾烟雾报警系统(GUI界面)

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、火灾烟雾报警系统四. 总结 一项目简介 YoloV5 是深度学习中用于目标检测的一种算法&#xff0c;可以对输入的图像进行识别&#xff0c;标识出…