webgl-图形非矩阵旋转
知识拓展
由(x1,y1)旋转β角度到(x2,y2)
根据圆极坐标方程
x1 = r*cosα
y1 = r*sinα
可得
x2 =r*cos(α + β)= r*cosα*cosβ - r*sinα*sinβ,因为x1 = r*cosα,y1 = r*sinα,所以x2 = x1*cosβ -y1*sinβ
y2 = r*sin(α + β) = r*sinα*cosβ + r*cosα*sinβ,因为x1 = r*cosα,y1 = r*sinα,所以y2 = y1* cosβ + x1*sinβ
因此
(x1,y1)旋转β角度到(x1*cosβ -y1*sinβ, y1* cosβ + x1*sinβ)
关键代码
//创建顶点资源和像素资源(颜色)
let vertexSource = `
attribute vec2 a_position;
attribute float cosB;
attribute float sinB;
void main() {
float x1 = a_position.x;
float y1 = a_position.y;
float x2 = x1*cosB - y1*sinB;
float y2 = x1*sinB + y1*cosB;
gl_Position = vec4(x2, y2, 0.0, 1.0);
gl_PointSize = 10.0;
}
`
html
<!DOCTYPE html>
<head>
<style>
*{
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id = 'webgl'>
您的浏览器不支持HTML5,请更换浏览器
</canvas>
<script src="./main.js"></script>
</body>
main.js
let canvas = document.getElementById('webgl')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
let radio = window.innerWidth/window.innerHeight;
let ctx = canvas.getContext('webgl')
//创建顶点资源和像素资源(颜色)
let vertexSource = `
attribute vec2 a_position;
attribute float cosB;
attribute float sinB;
void main() {
float x1 = a_position.x;
float y1 = a_position.y;
float x2 = x1*cosB - y1*sinB;
float y2 = x1*sinB + y1*cosB;
gl_Position = vec4(x2, y2, 0.0, 1.0);
gl_PointSize = 10.0;
}
`
let fragmentSource = `
precision mediump float;
void main (){
gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
`
if (initShader(ctx, vertexSource, fragmentSource)) {
//画三角形
let vertexs = [
// x y R G B
-0.5, 0.0, 1.0, 0.0, 0.0, //第一个点的信息
0.5, 0.0, 0.0, 1.0, 0.0, //第二个点的信息
0.0, 0.5, 0.0, 0.0, 1.0,//第三个点的信息
]
let float32Array = new Float32Array(vertexs)
//创建buffer
let buffer = ctx.createBuffer()
//绑定buffer
ctx.bindBuffer(ctx.ARRAY_BUFFER, buffer)
//往buffer中填充值,并指定数据用途
ctx.bufferData(ctx.ARRAY_BUFFER, float32Array, ctx.STATIC_DRAW)
//获取vertexShader指定变量内存
let a_Position = ctx.getAttribLocation(ctx.program, "a_position")
//指定每两个数组元素为一个点
/*
* 当数组元素不需进行分割拆分的时候最后两位可以指定为0,0
*
*
*/
ctx.vertexAttribPointer(
a_Position, //location: vertex Shader里面的attributes变量的location
2, ctx.FLOAT, //size: attribute变量的长度 vec2长度2 vec3长度3
false, //normalized: 正交化 true或false , [1, 2] => [1/根号5, 2/根号5]
5 * float32Array.BYTES_PER_ELEMENT, //stride: 每个点的信息所占的BYTES
0 //offset: 每个点的信息,从第几个BYTES开始数
)
ctx.enableVertexAttribArray(a_Position);
// ctx.drawArrays(ctx.TRIANGLE_FAN, 0, 3)
let angle = 0
function render(){
angle++
let cosB = ctx.getAttribLocation(ctx.program, "cosB")
let sinB = ctx.getAttribLocation(ctx.program, "sinB")
ctx.vertexAttrib1f(cosB, Math.cos(angle/180 * Math.PI))
ctx.vertexAttrib1f(sinB, Math.sin(angle/180 * Math.PI))
ctx.drawArrays(ctx.TRIANGLE_FAN, 0, 3)
window.requestAnimationFrame(render)
}
render()
}
//创建顶点阴影和像素阴影
function createShader(ctx, type, source) {
//创建shader
let shader = ctx.createShader(type)
//绑定
ctx.shaderSource(shader, source)
//编译shader
ctx.compileShader(shader)
//获取编译结果
let compiler = ctx.getShaderParameter(shader, ctx.COMPILE_STATUS)
if (compiler) {
return shader
} else {
let log = ctx.getShaderInfoLog(shader)
console.log("compile shaders error", log)
//删除异常的shader,防止内存泄露
ctx.deleteShader(shader)
return null
}
}
function createProgram(ctx, vertexShader, fragmentShader) {
//创建program
let program = ctx.createProgram()
if (!program) {
return null
}
//点资源和像素资源合并
ctx.attachShader(program, vertexShader)
ctx.attachShader(program, fragmentShader)
ctx.linkProgram(program)
//获取linked的结果
let linked = ctx.getProgramParameter(program, ctx.LINK_STATUS)
if (linked) {
return program
} else {
//获取link错误信息
let log = ctx.getProgramInfoLog(program)
console.log("link program error", log)
//删除防止内存泄漏
ctx.delete(program)
ctx.deleteShader(vertexShader)
ctx.deleteShader(fragmentShader)
return null
}
}
function initShader(ctx, vertexSource, fragmentSource) {
let vertexShader = createShader(ctx, ctx.VERTEX_SHADER, vertexSource)
let fragmentShader = createShader(ctx, ctx.FRAGMENT_SHADER, fragmentSource)
let program = createProgram(ctx, vertexShader, fragmentShader)
if (program) {
ctx.useProgram(program)
//挂载到ctx
ctx.program = program
return true
} else {
return false
}
}
效果图