我有以下代码试图通过将星星放在圆圈上的点来绘制花圈。我可以绘制一颗星,但是当我尝试画一个花圈时,它只围绕圆形绘制一个分支,或者现在在圆上的一个点上绘制。我知道我如何嵌套modelViewMatrices有一个问题我无法想到进行转换的正确方法。我需要绘制星星,然后翻译整个星星。
function DrawWreath()
{
var radius = 0.5;
for (var i = 0; i < 1; i++) {
var theta = i * 30;
var x = radius * Math.cos(theta);
var y = radius * Math.sin(theta);
var t = translate(x, y, 0);
if (modelViewMatrix) {
modelViewMatrix = mult(modelViewMatrix, t) ;
} else {
modelViewMatrix = t;
}
modelViewStack.push(modelViewMatrix);
DrawOneStar();
modelViewMatrix = modelViewStack.pop();
}
}
function DrawOneStar()
{
// draw the full star
for (var i=1; i <= 5; i++) {
r = rotate(72*i, 0, 0, 1);
if (modelViewMatrix) {
modelViewMatrix = mult(r, modelViewMatrix) ;
} else {
modelViewMatrix = r;
}
modelViewMatrix = r;
DrawOneBranch();
}
}
function DrawOneBranch()
{
var s;
// one branch
s = scale4(1/16, 1/16, 1);
modelViewStack.push(modelViewMatrix);
modelViewMatrix = mult(modelViewMatrix, s);
gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(modelViewMatrix));
gl.drawArrays( gl.LINE_LOOP, 0, vertices.length);
/*
modelViewMatrix = modelViewStack.pop();
//s = scale4(1/8, -1/8, 1);
modelViewMatrix = mult(modelViewMatrix, s);
gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(modelViewMatrix));
gl.drawArrays( gl.LINE_STRIP, 0, vertices.length);
*/
}
答案 0 :(得分:0)
代码有很多问题
DrawOneStar
中的代码在左侧旋转
mult(r, modelViewMatrix) // ???
好像你想要这个
mult(modelViewMatrix, r)
就像您使用translate
和scale
DrawOneStar
中的代码未保存矩阵
这意味着您要么修复代码以便保存 矩阵或,你想旋转固定的数量。
现在代码正在旋转72,然后旋转72 + 144,然后旋转 72 + 144 + 216,因为它每次都在旋转矩阵 旋转的
DrawOneBranch
中的代码未弹出矩阵
该行已注释掉
theta
正在使用学位
大多数数学库使用弧度,因此这段代码可能没有用 你期待什么
var theta = i * 30;
var x = radius * Math.cos(theta);
var y = radius * Math.sin(theta);
Math.sin
和Math.cos
要求弧度不是度数。
外部循环只进行一次迭代
for (var i = 0; i < 1; i++) { // ???
其他建议
使用更好的数学库。无论数学库需要调用flatten
函数来准备WebGL可以使用的矩阵,都会比没有算术库要慢。另外一个采用弧度进行旋转和视野的库意味着它将匹配其他内置数学函数,如Math.cos
等...
在modelViewMatrix
中添加一个矩阵即可开始。然后,您可以删除所有检查是否存在矩阵
在循环和计算值时,请考虑使用标准化数字(数字从0到1),然后根据该值计算其他值。
例如,代码在外部循环中有theta = i * 30
,在下一个循环中有rotate(i * 72, ...)
,但如果更改迭代次数,则还必须更改这些数字以匹配。
而是首先根据循环计算从0到1的值。实施例
const numStars = 10;
for (let i = 0; i < numStars; ++i) {
const l = i / numStars; // goes from 0 to 1
然后使用该值计算角度;
const theta = l * 360; // or l * Math.PI * 2 for radians
同样
const numRotations = 5;
for (let i = 0; i < numRotations; ++i) {
const l = i / numRotations; // goes from 0 to 1
rotate(i * 360, ....
这样,您可以轻松更改numStars
和numRotations
,而不是
必须更改任何其他代码
function DrawWreath()
{
var radius = 0.5;
for (var i = 0; i < 10; i++) {
var theta = i / 10 * Math.PI * 2;
var x = radius * Math.cos(theta);
var y = radius * Math.sin(theta);
var t = translate(x, y, 0);
modelViewStack.push(modelViewMatrix);
modelViewMatrix = mult(modelViewMatrix, t) ;
DrawOneStar();
modelViewMatrix = modelViewStack.pop();
}
}
function DrawOneStar()
{
// draw the full star
for (var i=1; i <= 5; i++) {
var r = rotate(72, 0, 0, 1);
modelViewMatrix = mult(modelViewMatrix, r) ;
DrawOneBranch();
}
}
function DrawOneBranch()
{
var s;
// one branch
s = scale4(1/16, 1/16, 1);
modelViewStack.push(modelViewMatrix);
modelViewMatrix = mult(modelViewMatrix, s);
gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(modelViewMatrix));
gl.drawArrays( gl.LINE_LOOP, 0, vertices.length);
modelViewMatrix = modelViewStack.pop();
/*
//s = scale4(1/8, -1/8, 1);
modelViewMatrix = mult(modelViewMatrix, s);
gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(modelViewMatrix));
gl.drawArrays( gl.LINE_STRIP, 0, vertices.length);
*/
}
function flatten(m) {
return m;
}
function translate(x, y, z) {
return m4.translation([x, y, z]);
}
function scale4(x, y, z) {
return m4.scaling([x, y, z]);
}
function rotate(a, x, y, z) {
return m4.axisRotation([x, y, z], a * Math.PI / 180);
}
function mult(a, b) {
return m4.multiply(a, b);
}
const m4 = twgl.m4;
const gl = document.querySelector("canvas").getContext("webgl");
const modelViewStack = [];
let modelViewMatrix = m4.identity();
const vs = `
attribute vec4 position;
uniform mat4 u_projectionMatrix;
uniform mat4 u_modelViewMatrix;
void main() {
gl_Position = u_projectionMatrix * u_modelViewMatrix * position;
}
`;
const fs = `
void main() { gl_FragColor = vec4(1,0,0,1); }
`;
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: {
numComponents: 2,
data: [
0, 1,
-.33, 0,
.33, 0,
],
},
});
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const scale = 1;
twgl.setUniforms(programInfo, {
u_projectionMatrix: m4.ortho(
-aspect / scale, aspect / scale, -1 / scale, 1 / scale, -1, 1),
u_modelViewMatrix: m4.identity(),
});
const vertices = { length: 3, };
const modelViewMatrixLoc = gl.getUniformLocation(programInfo.program, "u_modelViewMatrix");
DrawWreath();
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
<canvas></canvas>
还有一件事,不是手动计算cirlce上的位置,你也可以使用矩阵函数,旋转,然后翻译
function DrawWreath()
{
const radius = 0.5;
const numStars = 20;
for (let i = 0; i < numStars; ++i) {
const l = i / numStars;
const theta = l * Math.PI * 2;
const r = rotateInRadians(theta, 0, 0, 1);
const t = translate(radius, 0, 0);
modelViewStack.push(modelViewMatrix);
modelViewMatrix = mult(modelViewMatrix, r);
modelViewMatrix = mult(modelViewMatrix, t);
DrawOneStar();
modelViewMatrix = modelViewStack.pop();
}
}
function DrawOneStar()
{
// draw the full star
const numParts = 6;
for (let i = 0; i < numParts; ++i) {
const l = i / numParts;
const r = rotateInRadians(l * Math.PI * 2, 0, 0, 1);
modelViewStack.push(modelViewMatrix);
modelViewMatrix = mult(modelViewMatrix, r) ;
DrawOneBranch();
modelViewMatrix = modelViewStack.pop();
}
}
function DrawOneBranch()
{
var s;
// one branch
s = scale4(1/16, 1/16, 1);
modelViewStack.push(modelViewMatrix);
modelViewMatrix = mult(modelViewMatrix, s);
gl.uniformMatrix4fv(modelViewMatrixLoc, false, flatten(modelViewMatrix));
gl.drawArrays( gl.LINE_LOOP, 0, vertices.length);
modelViewMatrix = modelViewStack.pop();
}
function flatten(m) {
return m;
}
function translate(x, y, z) {
return m4.translation([x, y, z]);
}
function scale4(x, y, z) {
return m4.scaling([x, y, z]);
}
function rotate(a, x, y, z) {
return m4.axisRotation([x, y, z], a * Math.PI / 180);
}
function rotateInRadians(a, x, y, z) {
return m4.axisRotation([x, y, z], a);
}
function mult(a, b) {
return m4.multiply(a, b);
}
const m4 = twgl.m4;
const gl = document.querySelector("canvas").getContext("webgl");
const modelViewStack = [];
let modelViewMatrix = m4.identity();
const vs = `
attribute vec4 position;
uniform mat4 u_projectionMatrix;
uniform mat4 u_modelViewMatrix;
void main() {
gl_Position = u_projectionMatrix * u_modelViewMatrix * position;
}
`;
const fs = `
void main() { gl_FragColor = vec4(1,0,0,1); }
`;
const programInfo = twgl.createProgramInfo(gl, [vs, fs]);
const bufferInfo = twgl.createBufferInfoFromArrays(gl, {
position: {
numComponents: 2,
data: [
0, 1,
-.33, 0,
.33, 0,
],
},
});
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
const scale = 1;
twgl.setUniforms(programInfo, {
u_projectionMatrix: m4.ortho(
-aspect / scale, aspect / scale, -1 / scale, 1 / scale, -1, 1),
u_modelViewMatrix: m4.identity(),
});
const vertices = { length: 3, };
const modelViewMatrixLoc = gl.getUniformLocation(programInfo.program, "u_modelViewMatrix");
DrawWreath();
body { margin: 0; }
canvas { width: 100vw; height: 100vh; display: block; }
<script src="https://twgljs.org/dist/3.x/twgl-full.min.js"></script>
<canvas></canvas>
您可能会找到these articles useful