webgl中的旋转曲线
Rotate curve in webgl
我用线段近似曲线:
for (i=1; i<=100; i=i+0.2)
{
arr = calculateCurve(i, 1, 1, 1, 1); //function returns an array of verticles
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
prevArr[0]/scale,
prevArr[1]/scale,
prevArr[2]/scale,
arr[0]/scale,
arr[1]/scale,
arr[2]/scale
]), gl.STATIC_DRAW);
gl.drawArrays(gl.LINES, 0, 2);
prevArr = arr;
}
我需要在不使用 gl.drawArrays() 的情况下旋转曲线,因为在这种情况下性能非常慢。
我会创建一个包含 100 个顶点的巨大缓冲区,但我想知道是否有一种方法可以通过更改顶点着色器中的旋转矩阵来重绘场景。
不太清楚旋转曲线是什么意思。我看到至少有两种解释。一种是您希望曲线顶点位于同一位置但改变查看器位置,以便您可以从不同角度查看同一条曲线。第二个是你想要每一帧都有不同的曲线形状。
如果你想要的是 1),那么你所要做的就是将一个统一的矩阵发送到 GPU,然后在顶点着色器中执行 gl_Position = matrix * position
。这样做意味着您不必每帧都重新生成曲线上的顶点位置。
如果你想要的是2),那么你需要想出一些数学来计算顶点着色器中曲线上每个点的位置。如何做到这一点取决于具体情况,我认为您需要展示更多关于如何计算曲线位置的代码。
创建 "huge" 缓冲区在这里不是问题,缓冲区的大小甚至达不到 10kb(如果您使用不同于 LINE
-> LINE_LOOP
或LINE_STRIP
),但是多次调用 glDrawArrays
是。
这里正确的方法是缓冲孔线。为此生成一个 Float32Array
,其大小可以容纳所有要渲染的浮点数。然后恰好调用 glBufferData
和 glDrawArrays
一次。
如果您不每帧都更改线条,您也可以在第一次缓冲线条后跳过 glBufferData
。
您可以通过将顶点乘以旋转矩阵来旋转 WebGL 中的顶点。
例如,此代码将生成一个在 Z 轴上旋转顶点的矩阵。
function rotationZ(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
];
}
这是一个工作示例:
function rotationZ(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
];
}
// Using TWGL (twgljs.org) to keep the code small
var gl = document.getElementById("c").getContext("webgl");
// compiles shader, links and looks up locations
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
// make some curve points
points = [];
for (var i = 0; i < 100; ++i) {
var a = i / 100 * Math.PI * 2;
var r = 0.5;
points.push(
Math.sin(Math.sin(a * 2.)) * r ,
Math.cos(a) * r);
}
var arrays = {
position: { numComponents: 2, data: points, },
};
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
function render(time) {
var uniforms = {
u_matrix: rotationZ(time * 0.001),
};
gl.useProgram(programInfo.program);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
// calls gl.uniformXXX, gl.activeTexture, gl.bindTexture
twgl.setUniforms(programInfo, uniforms);
// calls gl.drawArray or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo, gl.LINE_LOOP);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid blue; }
<!--
note! I'm using a square canvas so I don't have to deal with aspect
which would complicate the example
See the articles linked in the answer for details about aspect
-->
<canvas id="c" width="150" height="150"></canvas>
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
<script id="vs" type="notjs">
attribute vec4 position;
uniform mat4 u_matrix;
void main() {
gl_Position = u_matrix * position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
void main() {
gl_FragColor = vec4(0,0,0,1);
}
</script>
This article explains how rotation works 其后的文章将过渡到使用矩阵。
我用线段近似曲线:
for (i=1; i<=100; i=i+0.2)
{
arr = calculateCurve(i, 1, 1, 1, 1); //function returns an array of verticles
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
prevArr[0]/scale,
prevArr[1]/scale,
prevArr[2]/scale,
arr[0]/scale,
arr[1]/scale,
arr[2]/scale
]), gl.STATIC_DRAW);
gl.drawArrays(gl.LINES, 0, 2);
prevArr = arr;
}
我需要在不使用 gl.drawArrays() 的情况下旋转曲线,因为在这种情况下性能非常慢。 我会创建一个包含 100 个顶点的巨大缓冲区,但我想知道是否有一种方法可以通过更改顶点着色器中的旋转矩阵来重绘场景。
不太清楚旋转曲线是什么意思。我看到至少有两种解释。一种是您希望曲线顶点位于同一位置但改变查看器位置,以便您可以从不同角度查看同一条曲线。第二个是你想要每一帧都有不同的曲线形状。
如果你想要的是 1),那么你所要做的就是将一个统一的矩阵发送到 GPU,然后在顶点着色器中执行 gl_Position = matrix * position
。这样做意味着您不必每帧都重新生成曲线上的顶点位置。
如果你想要的是2),那么你需要想出一些数学来计算顶点着色器中曲线上每个点的位置。如何做到这一点取决于具体情况,我认为您需要展示更多关于如何计算曲线位置的代码。
创建 "huge" 缓冲区在这里不是问题,缓冲区的大小甚至达不到 10kb(如果您使用不同于 LINE
-> LINE_LOOP
或LINE_STRIP
),但是多次调用 glDrawArrays
是。
这里正确的方法是缓冲孔线。为此生成一个 Float32Array
,其大小可以容纳所有要渲染的浮点数。然后恰好调用 glBufferData
和 glDrawArrays
一次。
如果您不每帧都更改线条,您也可以在第一次缓冲线条后跳过 glBufferData
。
您可以通过将顶点乘以旋转矩阵来旋转 WebGL 中的顶点。
例如,此代码将生成一个在 Z 轴上旋转顶点的矩阵。
function rotationZ(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
];
}
这是一个工作示例:
function rotationZ(angleInRadians) {
var c = Math.cos(angleInRadians);
var s = Math.sin(angleInRadians);
return [
c, s, 0, 0,
-s, c, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
];
}
// Using TWGL (twgljs.org) to keep the code small
var gl = document.getElementById("c").getContext("webgl");
// compiles shader, links and looks up locations
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
// make some curve points
points = [];
for (var i = 0; i < 100; ++i) {
var a = i / 100 * Math.PI * 2;
var r = 0.5;
points.push(
Math.sin(Math.sin(a * 2.)) * r ,
Math.cos(a) * r);
}
var arrays = {
position: { numComponents: 2, data: points, },
};
// calls gl.createBuffer, gl.bindBuffer, gl.bufferData for each array
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
function render(time) {
var uniforms = {
u_matrix: rotationZ(time * 0.001),
};
gl.useProgram(programInfo.program);
// calls gl.bindBuffer, gl.enableVertexAttribArray, gl.vertexAttribPointer
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
// calls gl.uniformXXX, gl.activeTexture, gl.bindTexture
twgl.setUniforms(programInfo, uniforms);
// calls gl.drawArray or gl.drawElements
twgl.drawBufferInfo(gl, bufferInfo, gl.LINE_LOOP);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid blue; }
<!--
note! I'm using a square canvas so I don't have to deal with aspect
which would complicate the example
See the articles linked in the answer for details about aspect
-->
<canvas id="c" width="150" height="150"></canvas>
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
<script id="vs" type="notjs">
attribute vec4 position;
uniform mat4 u_matrix;
void main() {
gl_Position = u_matrix * position;
}
</script>
<script id="fs" type="notjs">
precision mediump float;
void main() {
gl_FragColor = vec4(0,0,0,1);
}
</script>
This article explains how rotation works 其后的文章将过渡到使用矩阵。