WebGL动态绘制正多边形和正多角形
将WebGL绘图底层逻辑进行封装,引入vue项目
glsl.config.js文件
点击查看代码
// 使用webgl绘制三角形
// canvas是画布,pointArr绘制的点数据
export const webglFunction = (canvas, pointArr) => {
// 1创建webgl上下文
const webgl = canvas.getContext('webgl')
// 2创建webgl程序
// 创建顶点着色器和片元着色器
// 声明变量,类型为vec2(二维向量) 变量名
// GLSL编程语言
// 通过 gl_Position 设置顶点
// 顶点着色器
const vertex = `attribute vec2 position;
varying vec3 color;
void main() {
gl_PointSize = 1.0;
color = vec3(0.5 + position * 0.5, 0.0);
gl_Position = vec4(position * 0.5, 1.0, 1.0);
}`
// // 通过 gl_Position 设置顶点
// // 片元着色器
const fragment = `precision mediump float;
varying vec3 color;
void main() {
gl_FragColor = vec4(color, 1.0);
}`
const vertexShader = webgl.createShader(webgl.VERTEX_SHADER)
webgl.shaderSource(vertexShader, vertex)
webgl.compileShader(vertexShader)
const fragmentShader = webgl.createShader(webgl.FRAGMENT_SHADER)
webgl.shaderSource(fragmentShader, fragment)
webgl.compileShader(fragmentShader)
// 创建 WebGLProgram 对象,并将vertexShader和fragmentShader关联到webgl程序上
const program = webgl.createProgram()
webgl.attachShader(program, vertexShader)
webgl.attachShader(program, fragmentShader)
// 并将WebGLProgram 对象链接到webgl上下文
webgl.linkProgram(program)
// 启用WebGLProgram对象,在绘制图形时,gpu会自动去执行WebGLProgram对象设定的两个shader
webgl.useProgram(program)
// 3将数据存入缓冲区
const points = pointArr
// 创建一个缓存对象
const bufferId = webgl.createBuffer()
webgl.bindBuffer(webgl.ARRAY_BUFFER, bufferId)
// 把当前数据写入缓存对象
webgl.bufferData(webgl.ARRAY_BUFFER, points, webgl.STATIC_DRAW)
// 4将缓冲区数据读取到gpu上
// 获取顶点着色器中的position变量的地址
const vPosition = webgl.getAttribLocation(program, 'position')
// 给变量设置长度和类型
webgl.vertexAttribPointer(vPosition, 2, webgl.FLOAT, false, 0, 0)
// 激活这个变量
webgl.enableVertexAttribArray(vPosition)
// 5执行着色器程序完成绘制
// 将当前画布的内容清除
webgl.clear(webgl.COLOR_BUFFER_BIT)
// 传入绘制模式,以三角形为图元绘制,再传入绘制的顶点偏移量和顶点数量
webgl.drawArrays(webgl.TRIANGLE_FAN, 0, points.length / 2)
}
一、实现正多边形绘制
实现思路
![image]()
点击查看代码
<template>
<h4>WebGL绘图实现正多边形</h4>
<a-form layout="inline" :form="form" class="form">
<a-form-item label='正多边形的边数'>
<a-input-number v-decorator="[
'count',
{
initialValue: count,
rules: [{ required: true, message: 'count不能为空' }]
}
]"
:min="3"
:step="1">
</a-input-number>
</a-form-item>
<a-form-item label='半径长度'>
<a-input-number v-decorator="[
'length',
{
initialValue: length,
rules: [{ required: true, message: 'length不能为空' }]
},
]"
:min="0.5"
:max="2"
:step="0.1">
</a-input-number>
</a-form-item>
<a-form-item>
<a-button type="primary" ghost @click="product" html-type="submit">
生成正多边形
</a-button>
</a-form-item>
</a-form>
<canvas width="400" height="400" class="webgl"></canvas>
</template>
<script>
import { webglFunction } from './glsl.config'
export default {
name: 'WebGL',
props: {
},
components: {
},
data () {
return {
canvas: null,
count: 3,
length: 0.5,
form: this.$form.createForm(this, { name: 'input' }),
}
},
created () {
},
mounted () {
// 1创建webgl上下文
this.canvas = document.getElementsByClassName('webgl')[0]
this.webglRender()
},
watch: {
},
methods: {
// 使用webgl绘制三角形
webglRender () {
webglFunction(this.canvas, new Float32Array([-1, -1, 0, 1, 1, -1]))
},
// 生成指定规格的正多边形
product () {
const points = []
const { count, length } = this.form.getFieldsValue()
for (let i = 0; i < count; i++) {
const deg = Math.PI * 2 * i / count
const x = Math.cos(deg) * length
const y = Math.sin(deg) * length
points.push(x, y)
}
webglFunction(this.canvas, new Float32Array(points))
}
}
}
</script>
实现效果图
![image]()
二、实现正多角形绘制
实现思路
![image]()
点击查看代码
<template>
<h4>WebGL绘图实现正多角形</h4>
<a-form layout="inline" :form="formStart" class="form">
<a-form-item label='正多角形的角数'>
<a-input-number v-decorator="[
'countStart',
{
initialValue: countStart,
rules: [{ required: true, message: 'countStart不能为空' }]
}
]"
:min="5"
:step="1">
</a-input-number>
</a-form-item>
<a-form-item label='正多角形半径'>
<a-input-number v-decorator="[
'lengthStart',
{
initialValue: lengthStart,
rules: [{ required: true, message: 'lengthStart不能为空' }]
},
]"
:min="0.5"
:max="2"
:step="0.1">
</a-input-number>
</a-form-item>
<a-form-item>
<a-button type="primary" ghost @click="productStart" html-type="submit">
生成正多角形
</a-button>
</a-form-item>
</a-form>
<canvas width="400" height="400" class="webglStart"></canvas>
</template>
<script>
import { webglFunction } from './glsl.config'
export default {
name: 'WebGL',
props: {
},
components: {
},
data () {
return {
webglStart: null,
countStart: 5,
lengthStart: 0.5,
formStart: this.$form.createForm(this, { name: 'inputStart' })
}
},
created () {
},
mounted () {
// 1创建webgl上下文
this.webglStart = document.getElementsByClassName('webglStart')[0]
if (this.webglStart) {
this.productStart()
}
},
watch: {
},
methods: {
// 绘制正多角形
productStart () {
const points = [0, 0]
const { countStart, lengthStart } = this.formStart.getFieldsValue()
let x, y
for (let i = 0; i <= countStart * 2; i++) {
const degBig = Math.PI * 2 * i / (countStart * 2)
if (i % 2) {
x = Math.cos(degBig) * lengthStart
y = Math.sin(degBig) * lengthStart
} else {
x = Math.cos(degBig) * lengthStart / 2
y = Math.sin(degBig) * lengthStart / 2
}
points.push(x, y)
}
webglFunction(this.webglStart, new Float32Array(points))
}
}
}
</script>
实现效果图
![image]()