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

5、webgl基本概念 + 绘制多边形 + 绘制圆 + 绘制圆环

基本概念

如何绘制圆

可以绘制顶点位置一致的连续三角形,当三角形的数量越多,底边越小的时候就画好了圆。

三角形的角度计算方式

let angle = i * Math.PI * 2 / n;

x 方向的位置坐标点

let pointx = radius * Math.cos(angle) + x

y 方向的位置坐标点

let pointy = radius * Math.sin(angle) + y

绘制多边形、圆、圆环

多边形绘制

当三角形的数量较少时候,我们绘制出来的其实是一个多边形
在这里插入图片描述

<!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);let positionBuffer = gl.createBuffer();let indexBuffer = gl.createBuffer();gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); // 绑定索引缓冲区gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);let pointsData = circlePoints(100, 100, 50, 8);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pointsData), gl.STATIC_DRAW);gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 4 * 5, 0);gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 4 * 5, 4* 2);// 启用这个位置数据gl.enableVertexAttribArray(a_position);gl.enableVertexAttribArray(a_color);gl.drawArrays(gl.TRIANGLE_FAN, 0, 10);// 生成圆的坐标数据, 传入 圆心坐标 x, y, 半径 radius, 三角形 个数 nfunction circlePoints(x, y, radius, n) {let points = [x, y, 1, 0, 0];for(let i = 0; i <= n; i++) {let angle = i * Math.PI * 2 / n;let pointx = radius * Math.cos(angle) + x, pointy = radius * Math.sin(angle) + y;// 坐标点 数据后面的三个随机数,是颜色 r g bpoints.push(pointx, pointy, Math.random(),Math.random(), Math.random() )}return points;}</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>webgl-圆绘制-三角形底边缩小就能形成圆</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);let positionBuffer = gl.createBuffer();let indexBuffer = gl.createBuffer();gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); // 绑定索引缓冲区gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);let pointsData = circlePoints(100, 100, 50, 50);gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pointsData), gl.STATIC_DRAW);gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 4 * 5, 0);gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 4 * 5, 4* 2);// 启用这个位置数据gl.enableVertexAttribArray(a_position);gl.enableVertexAttribArray(a_color);gl.drawArrays(gl.TRIANGLE_FAN, 0, 52);// 生成圆的坐标数据, 传入 圆心坐标 x, y, 半径 radius, 三角形 个数 nfunction circlePoints(x, y, radius, n) {let points = [x, y, 1, 0, 0];for(let i = 0; i <= n; i++) {let angle = i * Math.PI * 2 / n;let pointx = radius * Math.cos(angle) + x, pointy = radius * Math.sin(angle) + y;points.push(pointx, pointy, Math.random(),Math.random(), Math.random() )}return points;}</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);let positionBuffer = gl.createBuffer();let indexBuffer = gl.createBuffer();gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); // 绑定索引缓冲区gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);let pointsData = ciclequePoints(100, 100, 100, 50, 50).points;let indexData = ciclequePoints(100, 100, 100, 50, 50).indices;gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pointsData), gl.STATIC_DRAW);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STATIC_DRAW);gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 4 * 5, 0);gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 4 * 5, 4* 2);// 启用这个位置数据gl.enableVertexAttribArray(a_position);gl.enableVertexAttribArray(a_color);gl.drawElements(gl.TRIANGLES, indexData.length, gl.UNSIGNED_SHORT, 0); // 索引绘制// gl.drawArrays(gl.TRIANGLE_FAN, 0, 52);function ciclequePoints(x, y, outerRadius, innerRadius, n) {let points = []; // 点坐标let indices = []; // 索引let color = {r: 0, g: 0,b: 0}for(let i = 0; i <= n; i++) {color = {r: Math.random(),g: Math.random(),b: Math.random(),}let angle = i * Math.PI * 2 / n;let innerX = innerRadius * Math.cos(angle) + x , innerY = innerRadius * Math.sin(angle) + y;let outerX = outerRadius * Math.cos(angle) + x,outerY = outerRadius * Math.sin(angle) + y;points.push(innerX, innerY, color.r, color.g, color.b);points.push(outerX, outerY, color.r, color.g, color.b);let v0 = i *  2, v1 = v0 + 1, v2 = v0 + 2, v3 = v0 + 3;if(i === n) {// 最后一个点 连接第一个点即可v2 = 0;v3 = 1;}indices.push(v0, v1, v2, v2, v1, v3);}return {points,indices}}</script>
</body>
</html>

圆环-使用三角带 + 索引缓冲区进行绘制

三角带进行绘制的好处在于索引只需要存 4个。

<!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);let positionBuffer = gl.createBuffer();let indexBuffer = gl.createBuffer();gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); // 绑定索引缓冲区gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);let pointsData = ciclequePoints(100, 100, 100, 50, 50).points;let indexData = ciclequePoints(100, 100, 100, 50, 50).indices;gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(pointsData), gl.STATIC_DRAW);gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), gl.STATIC_DRAW);gl.vertexAttribPointer(a_position, 2, gl.FLOAT, false, 4 * 5, 0);gl.vertexAttribPointer(a_color, 3, gl.FLOAT, false, 4 * 5, 4* 2);// 启用这个位置数据gl.enableVertexAttribArray(a_position);gl.enableVertexAttribArray(a_color);// gl.TRIANGLE_STRIP 三角带绘制gl.drawElements(gl.TRIANGLE_STRIP, indexData.length, gl.UNSIGNED_SHORT, 0); // 索引绘制// gl.drawArrays(gl.TRIANGLE_FAN, 0, 52);function ciclequePoints(x, y, outerRadius, innerRadius, n) {let points = []; // 点坐标let indices = []; // 索引let color = {r: 0, g: 0,b: 0}for(let i = 0; i <= n; i++) {color = {r: Math.random(),g: Math.random(),b: Math.random(),}let angle = i * Math.PI * 2 / n;let innerX = innerRadius * Math.cos(angle) + x , innerY = innerRadius * Math.sin(angle) + y;let outerX = outerRadius * Math.cos(angle) + x,outerY = outerRadius * Math.sin(angle) + y;points.push(innerX, innerY, color.r, color.g, color.b);points.push(outerX, outerY, color.r, color.g, color.b);let v0 = i *  2, v1 = v0 + 1, v2 = v0 + 2, v3 = v0 + 3;if(i === n) {// 最后一个点 连接第一个点即可v2 = 0;v3 = 1;}indices.push(v0, v1, v2, v3); // 利用三角带绘制,每一组只需要四个顶点}return {points,indices}}// 生成圆的坐标数据, 传入 圆心坐标 x, y, 半径 radius, 三角形 个数 n// function circlePoints(x, y, radius, n) {//     let points = [x, y, 1, 0, 0];//     for(let i = 0; i <= n; i++) {//         let angle = i * Math.PI * 2 / n;//         let pointx = radius * Math.cos(angle) + x, pointy = radius * Math.sin(angle) + y;//         points.push(pointx, pointy, Math.random(),Math.random(), Math.random() )//     }//     return points;// }</script>
</body>
</html>
http://www.dtcms.com/a/561411.html

相关文章:

  • 触摸屏网站如何做电子商务网站建设清华大学
  • 北京做网站的大公司惠阳网站建设
  • 网站开发做什么简单wordpress 自动发卡
  • 毕业设计做网站教程深圳app定制开发多少钱
  • 4.2【2020统考真题】
  • 4.2【2022统考真题】
  • 13.C++:继承
  • 做我的世界壁纸网站VPS wordpress 教程
  • 扒下来的网站怎么做修改php做网站访问记录
  • jxWebUI--日期时间选择框
  • Linux防火墙配置:iptables与firewalld使用指南(附案例)
  • 毕业设计网站开发类题目济南营销型网站建设贵吗
  • 网站服务器维护价格wordpress主页链接失效
  • 销售网站建设考核指标旅游网站开发目的6
  • 路由器端口镜像的配置与实验(eNSP)
  • vagrant+virtualBox使用记录
  • c++:析构与异常——noexcept的隐形爆炸
  • JavaEE多线程进阶
  • 网站建设结课总结如何在亚马逊开店流程及费用
  • 学习网页制作的网站如何修改网站源文件
  • 停车场管理|停车预约管理|基于Springboot的停车场管理系统设计与实现(源码+数据库+文档)
  • 计算机网络---ICMP协议(Internet Control Message Protocol,互联网控制消息协议)
  • 网站如何做淘宝客网站做要钱
  • 做公司网站需要什么资料开源手机网站系统
  • 成都网站优化公司哪家好南京哪家网络公司做网站优化好
  • Java 通配符
  • java-learn(9):常见算法,collection框架
  • 海口网站建设维护网校 039 网站建设多少钱
  • 网站建设的频道是什么济南企业网站制作费用
  • 外卖餐饮小程序带商城系统餐桌预定点餐寄存排队等待在线点单程序