0

非常に基本的な質問があります。私はwebglが初めてで、単純な正方形を描こうとしています。行列操作に gl 行列ライブラリを使用しています。

Javascript コード:

squareVertexPositionBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
    vertices = [
         0.9,  0.9,  0.0,1.0,
        -0.9,  0.9,  0.0,1.0,
         0.9, -0.9,  0.0,1.0,
        -0.9, -0.9,  0.0,1.0

    ];


    squareVertexPositionBuffer.itemSize = 4;
    squareVertexPositionBuffer.numItems = 4;

    mat4.identity(pMatrix);
    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0, pMatrix);
    mat4.identity(mvMatrix);
    mat4.translate(mvMatrix, [-1.5, 0.0, -7.0]);

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,         squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
    setMatrixUniforms();
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);

シェーダー:

attribute vec3 aVertexPosition;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

varying vec3 debug;


void main(void) {
    gl_Position =  uPMatrix * uMVMatrix * vec4(aVertexPosition.xyz, 1.0);
    debug = aVertexPosition;
}

これはうまくいくようです。ここでは、モデル ビューとパースペクティブ マトリックスをユニフォームとしてシェーダー プログラムに渡し、そこに頂点座標を掛けています。しかし、JavaScript でモデル ビューとパースペクティブ マトリックスを乗算し、変更された頂点をシェーダーに渡すと、うまくいかないようです。

私は間違いを見つけることができません。大変助かります!

4

2 に答える 2

2

すぐに、いくつかの問題に気付きました。

1) 頂点シェーダーの入力属性が vertexAttribPointer に渡されたパラメーターと一致しません:

アトリビュートが 4 float 幅であることを指定しますが、頂点シェーダーはそれを vec3 として指定します。これらは一貫している必要があります。

2) 次のような enableVertexAttribArray への呼び出しが表示されません。

gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

頂点シェーダーが使用する頂点属性配列を有効にする必要があります。

3) 表示されているコードから、モデル マトリックス (アイデンティティ、変換) のみを指定しています。ビュー マトリックスを作成する必要があります。これを行う簡単な方法は、mat4.lookAt を呼び出すことです。次の定義があります。

mat4.lookAt = 関数 (目、中央、上、宛先)

eye はカメラの位置です center はカメラが見ている位置です 常に (0, 1, 0) である必要があります

例は次のとおりです。

目 = (0, 0, 1) 中心 = (0, 0, 0)

これにより、カメラが Z 軸の正方向に 1 単位下がり、原点を向くようになります。

これにモデル マトリックスを掛けると、モデルビュー マトリックスが得られます。


不足しているコードが多すぎるため、間違いが別の場所にあるかどうかを判断するのが難しくなっています。たとえば、フラグメント シェーダーは何をしますか?


画面に最初のプリミティブを表示しようとするときは、カリングと深度テストを無効にすることをお勧めします。また、フラグメント出力がクリア カラーと一致する場合に備えて、時間の経過とともにクリア カラーを変更します。

ジョン

于 2012-08-17T14:37:51.390 に答える
1

ジョンの回答で概説されている問題は調査する価値がありますが、プリミティブを適切にレンダリングできるようになっている場合、それらがこの問題の根本原因であるとは思いません。

どのシナリオがあなたに当てはまるかわからないため、回答を 2 つのセグメントに分割しました。

  • MVP の JavaScript バージョンをどのように構築しているかは示されていませんが、乗算構文が正しいことを再確認してください。次の形式にする必要があります。

    mat4.multiply(p, mv, mvp);
    

    ここpで、 は射影行列、mvはモデルビュー行列、mvpは受け取るモデルビュー射影行列 (結果が格納される場所) です。

  • 同様に、頂点位置自体をあらかじめ乗算している場合、正しい構文は次のとおりです。

    mat4.multiplyVec4(mvp, vertex, transformedVertex);
    

    ここmvpで、 はモデルビュー射影行列、vertexは変更されていない頂点 (a vec4)、transformedVertexvec4値が格納される場所です。このアプローチを使用する場合、GPU に送信する前に、頂点の配列を 1 つの連続する float の配列にフラット化する必要があります。

    と混同mat4.multiplyVec3しないように注意してくださいmat4.multiplyVec4。の 4 番目のコンポーネントは、乗算の前に にvertex設定する必要があります。1このように、 の 4 番目のコンポーネントをtransformedVertexGPU で使用して透視分割を実行できます (これは自動的に行われますが、正しい値を送信する必要があります)。

    vec3また、誤ってアトリビュートを GPU に送信し、そのアトリビュートが実際には typevec4である場合、4 番目のコンポーネントのデフォルトは 1.0 になることにも注意してください。これはしばしば便利ですが、JavaScript でこれらの値を事前に乗算している場合、厄介なバグにつながる可能性もあります。John が言うように、シェーダーの定義を JavaScript 側と一致させるようにしてください。これにより、長期的には混乱が少なくなります。

于 2012-08-17T15:09:44.967 に答える