WebGL系列教程五(使用索引绘制彩色立方体)

news2024/9/21 11:15:42

目录

  • 1 前言
  • 2 立方体
  • 3 开始绘制
    • 3.1 声明顶点和颜色
    • 3.2 使用索引绘制
    • 3.3 效果
    • 3.4 完整代码
  • 4 总结

1 前言

  上一讲我们讲了如何绘制彩色的三角形,这一讲我们来说如何绘制立方体。为什么几乎所有的WebGL教程总是从开始绘制三角形开始,因为三角形是最小的面,其他的一切图形都可以用三角形来拼接。好了,废话不多说,我们直接开整。

2 立方体

  一个立方体有8个顶点,如下图所示
在这里插入图片描述
  现在我们要把立方体的重心放到坐标轴原点去,回忆一下WebGL中的坐标系,X轴向右,Y轴向上,Z轴向外,这八个顶点的坐标和对应的颜色为:

顶点XYZ坐标颜色(RGB)
v01.0,1.0,1.0,1.0,1.0,1.0
v1-1.0,1.0,1.0,1.0,0.0,1.0
v2-1.0,-1.0,1.0,1.0,0.0,1.0
v31.0,-1.0,1.0,1.0,1.0,0.0
v41.0,-1.0,-1.0,1.0,0.0,1.0
v5-1.0,-1.0,-1.0,1.0,1.0,1.0
v6-1.0,1.0,-1.0,0.0,0.0,1.0
v71.0,1.0,-1.0,0.0,1.0,1.0

3 开始绘制

3.1 声明顶点和颜色

 <script id="vertex-shader" type="x-shader/x-vertex">
     //声明一个点,vec3表示3维向量
     attribute vec3 aPosition;
     attribute vec4 a_Color;
     varying vec4 v_Color;
     void main(){
     	 //点的位置,将vec3补齐为vec4
         gl_Position = vec4(aPosition,1.0);
         //传递颜色
         v_Color = a_Color;
     }
 </script>
 <script id="fragment-shader" type="x-shader/x-fragment">
     precision highp float;
     varying vec4 v_Color;
     void main(){
         //点的颜色,rgba形式
         gl_FragColor = v_Color;
     }
 </script>

3.2 使用索引绘制

  因为现在我们要使用顶点索引,因此就不能使用DrawArrays方法进行绘制了,改为使用DrawElements。

//顶点和颜色
let verticesColors = new Float32Array([
     1.0, 1.0, 1.0,   1.0,1.0,1.0,//v0 近平面 右上 颜色
    -1.0, 1.0, 1.0,   1.0,0.0,1.0,//v1 近平面 左上 颜色
    -1.0,-1.0, 1.0,   1.0,0.0,1.0,//v2 近平面 左下 颜色
     1.0,-1.0, 1.0,   1.0,1.0,0.0,//v3 近平面 右下 颜色
     1.0,-1.0,-1.0,   1.0,0.0,1.0,//v4 远平面 右下 颜色
    -1.0,-1.0,-1.0,   1.0,1.0,1.0,//v5 远平面 左下 颜色
    -1.0, 1.0,-1.0,   0.0,0.0,1.0,//v6 远平面 左上 颜色
     1.0, 1.0,-1.0,   0.0,1.0,1.0 //v7 远平面 右上 颜色
]);
//顶点索引
let indices = new Uint8Array([
    0,1,2,  0,2,3,//近平面
    4,5,6,  4,6,7,//远平面
    1,2,5,  1,5,6,//左平面
    0,3,4,  0,4,7,//右平面
    3,4,2,  3,5,2,//下平面
    0,7,6,  0,1,6 //上平面
]);
//使webgl视口和canvas画板一样大
gl.viewport(0, 0, canvas.width, canvas.height);
//开启深度检测
gl.enable(gl.DEPTH_TEST);
//顶点
let vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
let FSIZE = verticesColors.BYTES_PER_ELEMENT;
let a_Position = gl.getAttribLocation(program,'a_Position');
gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,FSIZE*6,0);
gl.enableVertexAttribArray(a_Position);
//颜色
var a_Color = gl.getAttribLocation(program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
gl.enableVertexAttribArray(a_Color);
//绑定索引缓冲
let indexBuffer =  gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);

3.3 效果

  为了使效果明显一点,我将立方体绕Y轴旋转了60度。虽然看起来效果还不错。但仍然能看到一些问题,比如左下角和右上角为什么有一条明显的连线?那是因为每个面都是由两个三角形组成的。每个三角形都有各自的颜色,当然在拼接的地方就能看到明显的颜色分隔了。我们在这里先留个问题,怎么样使每个面只保留一种颜色呢?
在这里插入图片描述

3.4 完整代码

let canvas = document.getElementById("canvas");
let gl = canvas.getContext("webgl");
let vertexSource = document.getElementById("vertex-shader").innerText;
let fragmentSource = document.getElementById("fragment-shader").innerText;
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader,vertexSource);
gl.shaderSource(fragmentShader,fragmentSource);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
console.log(gl.getShaderInfoLog(vertexShader));
console.log(gl.getShaderInfoLog(fragmentShader));
let program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
console.log(gl.getProgramInfoLog(program));
//开始正常的逻辑,绘制立方体
// Create a cube

//   v6----- v7
//   /|      /|
//  v1------v0|
//  | |     | |
//  | |v5---|-|v4
//  |/      |/
//  v2------v3

//顶点和颜色
let verticesColors = new Float32Array([
     1.0, 1.0, 1.0,   1.0,1.0,1.0,//v0 近平面 右上 颜色
    -1.0, 1.0, 1.0,   1.0,0.0,1.0,//v1 近平面 左上 颜色
    -1.0,-1.0, 1.0,   1.0,0.0,1.0,//v2 近平面 左下 颜色
     1.0,-1.0, 1.0,   1.0,1.0,0.0,//v3 近平面 右下 颜色
     1.0,-1.0,-1.0,   1.0,0.0,1.0,//v4 远平面 右下 颜色
    -1.0,-1.0,-1.0,   1.0,1.0,1.0,//v5 远平面 左下 颜色
    -1.0, 1.0,-1.0,   0.0,0.0,1.0,//v6 远平面 左上 颜色
     1.0, 1.0,-1.0,   0.0,1.0,1.0 //v7 远平面 右上 颜色
]);
//顶点索引
let indices = new Uint8Array([
    0,1,2,  0,2,3,//近平面
    4,5,6,  4,6,7,//远平面
    1,2,5,  1,5,6,//左平面
    0,3,4,  0,4,7,//右平面
    3,4,2,  3,5,2,//下平面
    0,7,6,  0,1,6 //上平面
]);
//使webgl视口和canvas画板一样大
gl.viewport(0, 0, canvas.width, canvas.height);
//开启深度检测
gl.enable(gl.DEPTH_TEST);
//顶点
let vertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER,verticesColors,gl.STATIC_DRAW);
let FSIZE = verticesColors.BYTES_PER_ELEMENT;
let a_Position = gl.getAttribLocation(program,'a_Position');
gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,FSIZE*6,0);
gl.enableVertexAttribArray(a_Position);
//颜色
var a_Color = gl.getAttribLocation(program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, FSIZE * 6, FSIZE * 3);
gl.enableVertexAttribArray(a_Color);
//绑定索引缓冲
let indexBuffer =  gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,indices,gl.STATIC_DRAW);
//绘制三角形,36个点,立方体是6个面,每个面2个三角形,索引数组元素类型gl.UNSIGNED_BYTE,从第0个索引开始绘制
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_BYTE, 0);

4 总结

  本节我们通过梳理立方体的顶点坐标和对应的颜色关系,使用索引绘制的方式,绘制除了一个彩色的立方体,关于立方体是怎么旋转的,我们会在后面的博文中进行讲解。目前我们还遗留了一个思考问题,那就是如何使立方体的每个面都保持一个颜色,希望读者认真思考,我们留在下节进行解答。

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

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

相关文章

搜狗输入法电脑版颜文字如何关闭(快捷键冲突)

在使用快捷键:CTRLShiftb的时候&#xff0c;发现这个快捷键与搜狗输入法的快捷键存在冲突。 解决办法 在输入法图标上&#xff0c;右键&#xff0c;选择更多设置 找到左侧的高级选项&#xff0c;然后在右侧找到颜文字&#xff0c;选择关闭即可。

响应式精品资源导航html5源码

源码介绍 一款响应式精品网站推荐导航源码&#xff0c;可以自己修改代码替换图标图片和指向网址。背景图支持自动替换&#xff0c;背景图可以在images中修改,本地双击html即可查看效果 效果预览 源码获取 响应式精品资源导航源码html5

计算机组成原理(7):I/O

1 I/O系统基本概念 * ​ 本节实际就是对 I/O 系统 的简易科普&#xff0c;重点内容会在后续展开介绍&#xff1b; 1.1 I/O 系统 所以的这些I/O设备也可称为外部设备 ​ I / O 接口 &#xff1a;负责协调 主机 与 外部设备 之间的数据传输&#xff1b; 【1】I/O设备作用&#xf…

C2A:灾难场景中人体检测数据集(猫脸码客 第185期)

亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 C2A D…

如何获取本地的SSH Key密钥

1 打开Windows PowerShell 2 打开 PowerShell 后&#xff0c;输入以下代码 ssh证书生成 ssh-keygen -t rsa -C “xxxxxxxxx.com(此处填写你的邮箱)” ssh-keygen -t rsa -C "2624686862qq.com 然后Enter键按三下&#xff0c;下面示意图中&#xff0c;我是已经生产了SSH密…

PDF扫描版文字识别OCR

PDF扫描版文字识别OCR 最近需要有对PDF扫码版进行文字可识别的需求&#xff0c;这里介绍一款工具挺好用的 这是一款开源的OCR工具 github地址 https://github.com/hiroi-sora/Umi-OCR 主要功能及特点 免费&#xff1a;本项目所有代码开源&#xff0c;完全免费。方便&#…

实战OpenCV之像素操作

基础入门 在OpenCV中&#xff0c;像素是最基本的操作单位。图像可以视为一个三维数组&#xff0c;其中第三维表示颜色通道。图像数据在内存中以连续或几乎连续的方式存储&#xff0c;对于多通道图像&#xff08;比如&#xff1a;BGR图像&#xff09;&#xff0c;每个像素的各通…

828华为云征文 | 云上私人数据管家,jMalCloud个人网盘在华为云Flexus的Docker化部署实践

华为云服务器Flexus X实例介绍 华为云Flexus云服务器X实例&#xff0c;是由国家科技进步奖获得者、华为公司Fellow、华为云首席架构师顾炯炯牵头研发。它基于擎天QingTian架构、瑶光云脑、盘古大模型等根技术创新&#xff0c;是业界首款应用驱动的柔性算力云服务器&#xff0c;…

USB Type-C 接口引脚定义,以及 USB 3.1 和 USB 3.2 的区别

USB Type-C 接口引脚定义 USB 3.1 和 USB 3.2 的区别&#xff08;摘自网络&#xff0c;未验证&#xff09;

Matlab对状态机建模的方法

【 线性代数 状态机 】良好的控制系统设计 (根据现有的情况总结出状态转移方程) 状态组件在设计时需要考虑的内容 AI 的逻辑 可以提供一个思路

ICM20948 DMP代码详解(16)

接前一篇文章&#xff1a;ICM20948 DMP代码详解&#xff08;15&#xff09; 上一回讲到了inv_icm20948_initialize函数中的inv_icm20948_initialize_lower_driver函数中的inv_icm20948_read_mems_reg函数中的inv_icm20948_set_chip_power_state函数。再次贴出该函数源码&#x…

[SUCTF 2019]CheckIn

1、文件上传题 2、先上传.user.ini&#xff0c;抓包&#xff0c;然后放包 .user.ini内容为&#xff1a; GIF89a auto_prepend_filetest.jpg 3、接着上传test.jpg&#xff0c;抓包&#xff0c;放包 test.jpg内容&#xff1a; GIF89a? <script languag…

一个基于Spring实现的热更新插件开发框架

前言 对于其他解释性语言来说&#xff0c;热更新根本不是什么事&#xff0c;但对于Java来说是多么的不容易&#xff0c;现在使用Java开发的热更新系统&#xff0c;基本使用JS编写脚本&#xff0c;然后用Java的JavaScript引擎来跑脚本。 spring-hot-plugin 现在有一款开源的S…

PDB自启动设置

1、自启动说明 方案一&#xff1a;oracle12.1只能使用触发器 方案二&#xff1a;oracle12.2可用ALTER pluggable DATABASE ALL save state; 高版本建议优先使用第二种模式 2、触发器模式 CREATE TRIGGER open_all_pdbs AFTER STARTUP ON DATABASE BEGIN EXECUTE IMMEDIA…

通过C# 裁剪PDF页面

在处理PDF文档时&#xff0c;有时需要精确地裁剪页面以适应特定需求&#xff0c;比如去除广告、背景信息或者仅仅是为了简化文档内容。 本文将指导如何使用免费.NET控件通过C#实现裁剪PDF页面。 免费库 Free Spire.PDF for .NET 支持在 .NET (C#, VB.NET, ASP.NET, .NET Core)…

JAVA优化物流生态聚合快递与云洋系统小程序源码

优化物流生态&#xff0c;聚合快递与云洋系统小程序 &#x1f69a; 开篇&#xff1a;物流新生态&#xff0c;从这里启航 在这个快节奏的时代&#xff0c;物流不仅是商品传递的桥梁&#xff0c;更是连接消费者与商家的关键纽带。你是否厌倦了繁琐的物流查询、不稳定的配送时效&…

[Python学习日记-16] 细讲数据类型——元组

[Python学习日记-16] 细讲数据类型——元组 简介 元组的创建和查看 元组的切片 元组的循环 元组的嵌套 简介 有些时候我们的列表数据不想被人修改时怎么办&#xff1f;就可以用元组存放。元组&#xff08;tuple&#xff09;其实是列表的兄弟类型&#xff0c;他们非常的相似…

springboot项目中 前端浏览器访问时遇到跨域请求问题CORS怎么解决?has been blocked by CORS policy

文章目录 现象解决方案1. **全局配置 CORS**2. **使用 CrossOrigin 注解**3. **配置 Spring Security**4. **自定义 CORS 过滤器** Spring Security 6.x 及其后续版本解决方案1. 使用 SecurityFilterChain 配置 CORS2. 重要配置说明3. 在生产环境中的最佳实践 现象 前端浏览器…

【题解】CF2008G

题意翻译 原题链接CF2008G 思路 由于操作次数不限&#xff0c;观察到所有操作都是可逆的&#xff0c;所以可以随便搞。然后观察mex函数&#xff0c;发现让所有数在不重复的情况下尽可能地小是最优的&#xff08;重复就浪费了&#xff09;。      先不考虑重复和 0 0 0&a…

Ali_Yun Port

Ali_Yun Port 云服务器端口