5

hereからチュートリアルを読んでいました。

<script class = "WebGL">
var gl;
function initGL() {
  // Get A WebGL context
  var canvas = document.getElementById("canvas");
  gl = getWebGLContext(canvas);
  if (!gl) {
    return;
  }
}
var positionLocation;
var resolutionLocation;
var colorLocation;
var translationLocation;
var rotationLocation;
var translation = [50,50];
var rotation = [0, 1];
var angle = 0;
function initShaders() {
  // setup GLSL program
  vertexShader = createShaderFromScriptElement(gl, "2d-vertex-shader");
  fragmentShader = createShaderFromScriptElement(gl, "2d-fragment-shader");
  program = createProgram(gl, [vertexShader, fragmentShader]);
  gl.useProgram(program);

  // look up where the vertex data needs to go.
  positionLocation = gl.getAttribLocation(program, "a_position");

  // lookup uniforms
  resolutionLocation = gl.getUniformLocation(program, "u_resolution");
  colorLocation = gl.getUniformLocation(program, "u_color");
  translationLocation = gl.getUniformLocation(program, "u_translation");
    rotationLocation = gl.getUniformLocation(program, "u_rotation");

  // set the resolution
  gl.uniform2f(resolutionLocation, canvas.width, canvas.height);
}
function initBuffers() {
  // Create a buffer.
  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  gl.enableVertexAttribArray(positionLocation);
  gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

  // Set Geometry.
  setGeometry(gl);
}

function setColor(red, green, blue) {
    gl.uniform4f(colorLocation, red, green, blue, 1);
}
// Draw the scene.
function drawScene() {
    // Clear the canvas.
    gl.clear(gl.COLOR_BUFFER_BIT);

    // Set the translation.
    gl.uniform2fv(translationLocation, translation);
    // Set the rotation.
    gl.uniform2fv(rotationLocation, rotation);

    // Draw the geometry.
    gl.drawArrays(gl.TRIANGLES, 0, 6);
}


// Fill the buffer with the values that define a letter 'F'.
function setGeometry(gl) {
/*Assume size1 is declared*/
    var vertices = [
         -size1/2, -size1/2,
         -size1/2, size1/2,
         size1/2, size1/2,
         size1/2, size1/2,
         size1/2, -size1/2,
         -size1/2, -size1/2 ];
      gl.bufferData(
         gl.ARRAY_BUFFER,
         new Float32Array(vertices),
         gl.STATIC_DRAW);
}
function animate() {
    translation[0] += 0.01;
    translation[1] += 0.01;
    angle += 0.01;
    rotation[0] = Math.cos(angle);
    rotation[1] = Math.sin(angle);
}
function tick() {
    requestAnimFrame(tick);
    drawScene();
    animate();
}
function start() {

    initGL();
    initShaders();
    initBuffers();
    setColor(0.2, 0.5, 0.5);
    tick();
}

</script>

<!-- vertex shader -->
<script id="2d-vertex-shader" type="x-shader/x-vertex">
    attribute vec2 a_position;

    uniform vec2 u_resolution;
    uniform vec2 u_translation;
    uniform vec2 u_rotation;
    void main() {
        vec2 rotatedPosition = vec2(
        a_position.x * u_rotation.y + a_position.y * u_rotation.x,
        a_position.y * u_rotation.y - a_position.x * u_rotation.x);

       // Add in the translation.
       vec2 position = rotatedPosition + u_translation;

       // convert the position from pixels to 0.0 to 1.0
       vec2 zeroToOne = position / u_resolution;

       // convert from 0->1 to 0->2
       vec2 zeroToTwo = zeroToOne * 2.0;

       // convert from 0->2 to -1->+1 (clipspace)
       vec2 clipSpace = zeroToTwo - 1.0;

       gl_Position = vec4(clipSpace, 0, 1);
    }
</script>
<!-- fragment shader -->
<script id="2d-fragment-shader" type="x-shader/x-fragment">
    precision mediump float;

    uniform vec4 u_color;

    void main() {
       gl_FragColor = u_color;
    }
</script>

1 つの形状の WebGL プログラムは、次のように機能します。

  1. canvas 要素からコンテキスト (gl) を取得します。
  2. オブジェクトの形状でバッファを初期化する
  3. drawScene(): への呼び出しgl.drawArrays()
  4. アニメーションがある場合は、形状の角度、位置、および のdrawScene()両方を更新する更新関数tick()が繰り返し呼び出されるようにします。

複数の形状が必要な場合は、単一のバッファーを一度に多くのオブジェクトで埋めてから、それを使用してdrawScene()すべてのオブジェクトを一度に描画する [または]initBufferdrawScene()from を繰り返し呼び出す必要がありrequestAnimFrame()ます。

4

3 に答える 3

3

1 つのバッファーに複数のメッシュがある (そして、gl.drawArrays()提案されているように 1 つのメッシュでレンダリングする) と、複雑なシーンでパフォーマンスが向上しますが、明らかにその時点で、メッシュごとにシェーダー ユニフォーム (変換など) を変更することはできません。

メッシュを独立して実行したい場合は、それぞれを個別にレンダリングする必要があります。呼び出しによるオーバーヘッドを回避するために、すべてのメッシュを 1 つのバッファに保持することもできますがgl.bindBuffer()、少なくとも単純なシーンではそれほど役に立ちません。

于 2012-10-22T20:04:39.557 に答える
1

シーンに必要なオブジェクトごとに個別にバッファを作成します。そうしないと、オブジェクトを個別に移動してシェーダー効果を使用することができなくなります。

ただし、それはオブジェクトが異なる場合です。私がここで得たものから、同じ形状を異なる位置に複数回描画したいだけだと思いますよね?

その方法はtranslationLocation、最初に形状を描画した後、別の変換行列を使用してそのユニフォームをすぐそこに設定することです。そうすれば、形状を再度描画すると、他の形状の上ではなく別の場所に配置されるため、それを見ることができます。gl.drawElements既に使用されている同じバッファを描画するため、これらすべての変換行列を別の方法で設定し、再度呼び出すことができます。

于 2012-10-23T02:55:08.303 に答える