4

私はhtml5rocksに関するいくつかのチュートリアルに従ってきましたが、webGLを使用してキャンバス上に1つの画像を表示するjavascriptプログラムを作成することができました。このために持っているコードを以下に投稿しました。

問題は、webGLで複数のオブジェクトを描画する方法を教えてくれる人は誰もいないようです。私はこれまでwebGLを直接操作したことがないので、あまり直感的ではありません。

このコードを変更して、?内の各オブジェクトを描画するにはどうすればよいimageObjectArrayですか?(今はただ描いていることに注意してimageObjectArray[0]ください。

    function render(canvas, contextGL, imageObjectArray) { 
        vertexShader = createShaderFromScriptElement(contextGL, "2d-vertex-shader");
        fragmentShader = createShaderFromScriptElement(contextGL, "2d-fragment-shader");

        program = createProgram(contextGL, [vertexShader, fragmentShader]);
        contextGL.useProgram(program);

        var positionLocation = contextGL.getAttribLocation(program, "a_position");

        var texCoordLocation = contextGL.getAttribLocation(program, "a_texCoord");

        var texCoordBuffer = contextGL.createBuffer();
        contextGL.bindBuffer(contextGL.ARRAY_BUFFER, texCoordBuffer);

        contextGL.enableVertexAttribArray(texCoordLocation);
        contextGL.vertexAttribPointer(texCoordLocation, 2, contextGL.FLOAT, false, 0, 0);

        setRectangle(contextGL, 0.0, 0.0, 1.0, 1.0);

        var texture = contextGL.createTexture();
        contextGL.bindTexture(contextGL.TEXTURE_2D, texture);

        contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_WRAP_S, contextGL.CLAMP_TO_EDGE);
        contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_WRAP_T, contextGL.CLAMP_TO_EDGE);
        contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_MIN_FILTER, contextGL.NEAREST);
        contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_MAG_FILTER, contextGL.NEAREST);

        contextGL.texImage2D(contextGL.TEXTURE_2D, 0, contextGL.RGBA, contextGL.RGBA, contextGL.UNSIGNED_BYTE, imageObjectArray[0].displayObject.data);

        var resolutionLocation = contextGL.getUniformLocation(program, "u_resolution");
        contextGL.uniform2f(resolutionLocation, canvas.width, canvas.height);

        var buffer = contextGL.createBuffer();
        contextGL.bindBuffer(contextGL.ARRAY_BUFFER, buffer);
        contextGL.enableVertexAttribArray(positionLocation);
        contextGL.vertexAttribPointer(positionLocation, 2, contextGL.FLOAT, false, 0, 0);

        setRectangle(contextGL, imageObjectArray[0].x, imageObjectArray[0].y, imageObjectArray[0].width, imageObjectArray[0].height);

        // draw
        contextGL.drawArrays(contextGL.TRIANGLES, 0, 6);
    }

function setRectangle(gl, x, y, width, height) {
    var x2 = x + width;
    var y2 = y + height;
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
                                        [x, y,
                                         x2, y,
                                         x, y2,
                                         x, y2,
                                         x2, y,
                                         x2, y2
                                        ]), gl.STATIC_DRAW);
}

ここでの私の目的は、(非常に基本的な)2Dスプライトゲームに取り組むことです。図書館の快適さなし。(多分glMatrix.jsを除いて)

[編集]レンダリング機能にエラーがあり、修正されました。

4

1 に答える 1

5

次のコードは次のことを行います。

  1. 頂点シェーダーとフラグメントシェーダーをコンパイルします
  2. それらをシェーダープログラムにリンクします
  3. テクスチャ座標を保持する頂点バッファを作成し、それを埋めます(texCoordBuffer)
  4. テクスチャを作成します(createTexture)
  5. テクスチャのサンプリング方法を設定します(texParameteri)

上記の5つの手順は、1回だけ実行する必要があります。

    vertexShader = createShaderFromScriptElement(contextGL, "2d-vertex-shader");
    fragmentShader = createShaderFromScriptElement(contextGL, "2d-fragment-shader");

    program = createProgram(contextGL, [vertexShader, fragmentShader]);
    contextGL.useProgram(program);

    var positionLocation = contextGL.getAttribLocation(program, "a_position");

    var texCoordLocation = contextGL.getAttribLocation(program, "a_texCoord");

    var texCoordBuffer = contextGL.createBuffer();
    contextGL.bindBuffer(contextGL.ARRAY_BUFFER, texCoordBuffer);

    contextGL.enableVertexAttribArray(texCoordLocation);
    contextGL.vertexAttribPointer(texCoordLocation, 2, contextGL.FLOAT, false, 0, 0);

    var texture = contextGL.createTexture();
    contextGL.bindTexture(contextGL.TEXTURE_2D, texture);

    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_WRAP_S, contextGL.CLAMP_TO_EDGE);
    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_WRAP_T, contextGL.CLAMP_TO_EDGE);
    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_MIN_FILTER, contextGL.NEAREST);
    contextGL.texParameteri(contextGL.TEXTURE_2D, contextGL.TEXTURE_MAG_FILTER, contextGL.NEAREST);

    setRectangle(contextGL, 0.0, 0.0, 1.0, 1.0);

残りのコードは、描画する画像ごとに実行する必要があり、次のように実行されます。

  1. 画像をテクスチャにアップロードします(texImage2D)
  2. 位置を保持する頂点バッファを作成し、それを埋めます(バッファ)
  3. drawArraysを呼び出します
    contextGL.texImage2D(contextGL.TEXTURE_2D、0、contextGL.RGBA、contextGL.RGBA、contextGL.UNSIGNED_BYTE、imageObjectArray [0] .displayObject.data);

    var resolutionLocation = contextGL.getUniformLocation(program、 "u_resolution");
    contextGL.uniform2f(resolutionLocation、canvas.width、canvas.height);

    var buffer = contextGL.createBuffer();
    contextGL.bindBuffer(contextGL.ARRAY_BUFFER、buffer);
    contextGL.enableVertexAttribArray(positionLocation);
    contextGL.vertexAttribPointer(positionLocation、2、contextGL.FLOAT、false、0、0);

    setRectangle(contextGL、imageObjectArray [0] .x、imageObjectArray [0] .y、imageObjectArray [0] .width、imageObjectArray [0] .height);

    // 描く
    contextGL.drawArrays(contextGL.TRIANGLES、0、6);

ステップ2を別々のステップに分割する必要があります。位置の頂点バッファを作成する最初のステップは、1回だけ実行する必要があります。画像の位置を埋める2番目のステップは、描画する画像ごとに実行する必要があります。

私の提案では最適な実装は得られませんが、複数の画像を描画することができます。最適にするには、次のことを検討する必要があります。

  • テクスチャアトラスを実装します(すべての画像を単一のテクスチャにパックします)。
  • テクスチャと位置座標を一度だけアップロードします。
  • より適切な頂点シェーダーとフラグメントシェーダーを使用して、描画される画像(テクスチャ座標オフセット)、描画される場所(位置オフセット)、および画像の大きさ(幅と高さのスケーリング)を選択します。
于 2012-09-07T16:45:33.110 に答える