将整个形状移动到Circle WebGL上



我有以下代码试图通过将恒星放在圆上来绘制花圈。我能够画一颗恒星,但是当我尝试画一块花圈时,只会在圆圈周围或圆圈上的一个点绘制一个分支。我知道我如何嵌套模型视图的方式存在问题,我想不出要进行转换的正确方法。我需要画恒星,然后翻译整个星星。

   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);
    */
}

代码的许多问题

  • DrawOneStar中的代码在左侧旋转

    mult(r, modelViewMatrix)    // ???
    

    似乎您想要这个

    mult(modelViewMatrix, r)
    

    就像您对translatescale

  • 一样
  • 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.sinMath.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, ....
    

    这样,您可以轻松更改numStarsnumRotations而不是必须更改任何其他代码

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>

您可能会发现这些文章有用

相关内容

  • 没有找到相关文章

最新更新