[解決済み] Emscripten/OpenGLのコードで「glDrawArrays: attribute 1の範囲外の頂点にアクセスしようとする」(ネイティブC++では動作する) [終了しました]
質問
問題を絞り込むと、こうなります。 全く同じデータを指している属性が2つある。 これは、ネイティブC++でビルドした場合は正常に動作します。 しかし、emscriptenでビルドすると、javascriptコンソールに各フレームで次のエラーが表示されます。
'glDrawArrays: attempt to access out of range vertices in attribute 1'
glEnableVertexAttribArray」の行をコメントアウトして2つ目のアトリビュートを有効にすると、このエラーは発生しません。
以下は私のコードです。 まず、データバッファの作成から始めます。
GLfloat rectangleData[] =
{
-.5f, -.5f, 0,1,
-.5f, .5f, 0,0,
.5f, .5f, 1,0,
.5f, -.5f, 1,1,
-.5f, -.5f, 0,1
};
glGenBuffers(1, &rectangleBuffer);
glBindBuffer(GL_ARRAY_BUFFER, rectangleBuffer);
glBufferData(
GL_ARRAY_BUFFER, sizeof(rectangleData),
rectangleData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
以下は、私のテクスチャ付き四角形描画コードからの関連する抜粋です。
glBindBuffer(GL_ARRAY_BUFFER, rectangleBuffer);
int vertexPosition = Shader::getParameterInfo("vertexPosition")->id;
glVertexAttribPointer(
vertexPosition, 2, GL_FLOAT,
GL_FALSE, 16, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vertexPosition);
int vertexTexCoord = Shader::getParameterInfo("vertexTexCoord")->id;
glVertexAttribPointer(
vertexTexCoord, 2, GL_FLOAT,
GL_FALSE, 16, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vertexTexCoord);
glDrawArrays(GL_TRIANGLE_FAN, 0, 5);
2番目の属性は、1番目の属性と同じデータを指すように調整していることに注意してください(デバッグ時の複雑さを軽減するため)。 私はここでかなり困っていて、新鮮で経験豊富な視点を本当に利用したいです。
編集:以下は
BUFFER_OFFSET
のように見えます。
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
出典 int を const GLvoid* にキャストするには?
EDIT: 参考までに、同等のEmscriptenが生成したJSコードを以下に示します。 要求があれば、これが参照するJSコードも掲載します。
dest=$rectangleData; src=2328; stop=dest+80|0; do {
HEAP32[dest>>2]=HEAP32[src>>2]|0; dest=dest+4|0; src=src+4|0; } while
((dest|0) < (stop|0));
_glGenBuffers(1,(2300|0));
$30 = HEAP32[2300>>2]|0;
_glBindBuffer(34962,($30|0));
_glBufferData(34962,80,($rectangleData|0),35044);
_glBindBuffer(34962,0);
$11 = HEAP32[2300>>2]|0;
_glBindBuffer(34962,($11|0));
$12 = (__ZN8platform6Shader16getParameterInfoEPKc(17356)|0);
$13 = HEAP32[$12>>2]|0;
$vertexPosition = $13;
$14 = $vertexPosition;
_glVertexAttribPointer(($14|0),2,5126,0,16,(0|0));
$15 = $vertexPosition;
_glEnableVertexAttribArray(($15|0));
$16 = (__ZN8platform6Shader16getParameterInfoEPKc(17379)|0);
$17 = HEAP32[$16>>2]|0;
$vertexTexCoord = $17;
$18 = $vertexTexCoord;
_glVertexAttribPointer(($18|0),2,5126,0,16,(0|0));
$19 = $vertexTexCoord;
_glEnableVertexAttribArray(($19|0));
_glDrawArrays(6,0,5);
Edit: もっといいのは、githubで動いているJSコードへのリンクと、C++コードも提供することです("drawImage()"の一番下付近にあります)。
解決方法は?
問題は、1つの頂点シェーダで 常に2つのアトリビュートを使用する
var gl = document.createElement("canvas").getContext("webgl");
var program = twgl.createProgramFromScripts(gl, ["vs", "fs"]);
log("list of used attributes");
log("-----------------------");
var numAttribs = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
for (var ii = 0; ii < numAttribs; ++ii) {
var attribInfo = gl.getActiveAttrib(program, ii);
if (!attribInfo) {
break;
}
log(gl.getAttribLocation(program, attribInfo.name), attribInfo.name);
}
function log(...args) {
var div = document.createElement("div");
div.textContent = [...args].join(" ");
document.body.appendChild(div);
}
<script src="https://twgljs.org/dist/2.x/twgl.min.js"></script>
<script type="foo" id="vs">
uniform mat4 sceneTransform;
uniform mat4 rotationTransform;
uniform vec2 objectPosition;
uniform vec2 objectScale;
attribute vec2 vertexPosition;
attribute vec2 vertexTexCoord;
varying vec2 UVs;
void main()
{
UVs = vertexTexCoord;
gl_Position =
sceneTransform *
vec4( vertexPosition * objectScale + objectPosition, 0, 1);
}
</script>
<script type="foo" id="fs">
precision mediump float;
uniform vec3 objectColor;
uniform float objectOpacity;
void main()
{
gl_FragColor = vec4(objectColor, objectOpacity);
}
</script>
drawCircleを呼び出すと、これらの属性の両方がバッファに割り当てられますが、上記のコードでは、2番目の属性について何もしなければ、前のバッファを指したままです。このバッファは描画の呼び出しに対して小さすぎるため、エラーになります。
WebGLは未使用の属性については文句を言いませんが、使用済みの属性については文句を言います。シェーダが必要とする属性は常に提供すべきです。
あなたの場合、少なくとも2つのオプションがあります。
-
シェーダーが1つのアトリビュートしか使用しないようにコードを変更する。
コードを正しく読めば、バーテックスシェーダーは1つだけですね。フラグメントシェーダがテクスチャ座標を使用しない場合、テクスチャ座標を提供しない別のバーテックスシェーダを使用します。
-
属性を無効にして、定数値を使用するようにします。
gl.disableVertexAttribArray(...)
が提供する定数値を使用することを意味します。
gl.vertexAttribXXX
なぜなら、バーテックスシェーダはアトリビュートから読み込んで、それをフラグメントシェーダで使わないで、変化するものにコピーするという無駄な時間を過ごさないからです。
関連
-
[解決済み] テスト
-
[解決済み] Emscripten/OpenGLのコードで「glDrawArrays: attribute 1の範囲外の頂点にアクセスしようとする」(ネイティブC++では動作する) [終了しました]
-
[解決済み] glBlitFramebufferを使用してテクスチャを表示する
-
[解決済み] コンセプト:glDrawBufferとglDrawBuffersの使い分けは?
-
opengl glGetIntegerv エラーを使用します。アクセス違反 ロケーション0x0000000000000000を実行中
-
GLMライブラリの概要 glm::transform, glm:scale, glm::rotate
-
[解決済み] OpenGL - glDepthMaskの使い方についての質問です。
-
[解決済み] GL_COLOR_BUFFER_BITとGL_DEPTH_BUFFER_BITは何のためにあるのでしょうか?
-
[解決済み] GLSLシェーダーの正しいファイル拡張子は何ですか?[クローズド]。
-
[解決済み] glActiveTextureとglBindTextureの違いと関係
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] OpenGL - なぜ、インデックスのためのGL_ELEMENT_ARRAY_BUFFERなのですか?
-
[解決済み] glEnableVertexAttribArrayは具体的に何をするのですか?
-
[解決済み] Emscripten/OpenGLのコードで「glDrawArrays: attribute 1の範囲外の頂点にアクセスしようとする」(ネイティブC++では動作する) [終了しました]
-
[解決済み] 頂点シェーダとフラグメントシェーダにおけるgl_Colorとgl_FrontColorの関係を教えてください。
-
[解決済み] OpenGL GLXエクステンションはサポートされていません
-
GLMライブラリの概要 glm::transform, glm:scale, glm::rotate
-
[解決済み] GL_COLOR_BUFFER_BITとGL_DEPTH_BUFFER_BITは何のためにあるのでしょうか?
-
[解決済み】OpenGLのテキストレンダリングは、バージョン4.1現在、何が最先端なのでしょうか?[クローズド]。
-
[解決済み] GLSLシェーダーの正しいファイル拡張子は何ですか?[クローズド]。
-
[解決済み] バーテックスシェーダとフラグメントシェーダの比較 [重複].