2017-06-24 7 views
3

申し訳ありませんが、これは本当にばかだと。私は奇妙なWebGLの問題を抱えています。スプライトをレンダリングするための、本当に基本的なWebGLプログラムを作成しました。シンプルなWebGLプログラムでバッファをバインドする順序が問題になるのはなぜですか?

<!DOCTYPE html> 
<html lang="en"> 
<head><title></title> 
<style> 
html, body { height: 100%; margin: 0; padding: 0; overflow: hidden; } 
canvas { position: absolute; top:0;left:0; cursor: none; } 
</style></head><body> 
<canvas id="webgltestingthing"></canvas> 
<script> 
var scene,gl,cursor,sh={}; 

var vertexShader="\ 
precision mediump float;\ 
attribute vec2 a_position;\ 
attribute vec2 a_texCoord;\ 
uniform vec2 u_resolution;\ 
varying vec2 v_texCoord;\ 
void main() {\ 
    gl_Position = vec4(a_position/u_resolution*2.0-1.0, 0, 1);\ 
    v_texCoord = a_texCoord;\ 
}"; 
var fragShader="\ 
precision mediump float;\ 
uniform sampler2D u_image;\ 
varying vec2 v_texCoord;\ 
void main() {\ 
    gl_FragColor = texture2D(u_image, v_texCoord);\ 
}"; 

function resizeScene() { 
    document.getElementById("webgltestingthing").width = document.body.clientWidth; 
    document.getElementById("webgltestingthing").height = document.body.clientHeight; 
    if(gl) gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); } 
mouseX=-1000; mouseY=-1000; 
function trackMouse(e) { e = e || window.event; mouseX=event.pageX; mouseY=event.pageY; } 
function trackMouseOut() { mouseX=-1000; mouseY=-1000; } 
function createShader(gl, type, source) { 
    var shader = gl.createShader(type); 
    gl.shaderSource(shader, source); 
    gl.compileShader(shader); 
    var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); 
    if (success) { return shader; } 
    console.log(gl.getShaderInfoLog(shader)); gl.deleteShader(shader); } 
function createProgram(gl, vertexShader, fragmentShader) { 
    var program = gl.createProgram(); 
    gl.attachShader(program, vertexShader); 
    gl.attachShader(program, fragmentShader); 
    gl.linkProgram(program); 
    var success = gl.getProgramParameter(program, gl.LINK_STATUS); 
    if (success) { return {p: program, a: {}, u: {}}; } 
    console.log(gl.getProgramInfoLog(program)); gl.deleteProgram(program); } 
function createTexture(url,onload) { 
    this.img=new Image(); this.onload=onload; this.loaded=false; 
    this.img.src=url; 
    this.w=0; this.h=0; this.texture=gl.createTexture(); 
    gl.bindTexture(gl.TEXTURE_2D, this.texture); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 
    postload=function() { 
     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img); 
     this.loaded=true; this.onload(); } 
    this.img.addEventListener("load",postload.bind(this)); 
    return this; } 
function renderSprite(t,x,y) { 
    if(!t.loaded) return; 
    var x1=x,y1=scene.clientHeight-y,x2=x+t.img.width,y2=y1-t.img.height; 
    gl.activeTexture(gl.TEXTURE0); 
    gl.bindTexture(gl.TEXTURE_2D, t.texture); 
    gl.useProgram(sh.sprite.p); 

    gl.bindBuffer(gl.ARRAY_BUFFER, sh.sprite.a.texCoordBuffer); 
    gl.enableVertexAttribArray(sh.sprite.a.texCoord); 
    gl.vertexAttribPointer(sh.sprite.a.texCoord, 2, gl.FLOAT, false, 0, 0); 
    gl.bindBuffer(gl.ARRAY_BUFFER, sh.sprite.a.positionBuffer); 
    gl.enableVertexAttribArray(sh.sprite.a.position); 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]), gl.STATIC_DRAW); 
    gl.vertexAttribPointer(sh.sprite.a.position, 2, gl.FLOAT, false, 0, 0); 

    gl.uniform2fv(sh.sprite.u.res, [scene.clientWidth, scene.clientHeight]); 
    gl.uniform1i(sh.sprite.u.img, 0); 

    gl.drawArrays(gl.TRIANGLES, 0, 6); 
} 
function renderStuff() { 
    gl.clearColor(0, 0, 0, 0); 
    gl.clear(gl.COLOR_BUFFER_BIT); 
    if(mouseX>0) renderSprite(cursor,mouseX,mouseY); 
    requestAnimationFrame(renderStuff); 
} 
(function() { 
    scene=document.getElementById("webgltestingthing"); resizeScene(); 
    window.addEventListener('resize', resizeScene, true); 
    window.addEventListener('mousemove', trackMouse, true); 
    scene.addEventListener('mouseout', trackMouseOut, true); 
    gl=scene.getContext("experimental-webgl"); 

    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 
    sh.f_sprite = createShader(gl, gl.FRAGMENT_SHADER, fragShader); 
    sh.v_bypixels = createShader(gl, gl.VERTEX_SHADER, vertexShader); 

    sh.sprite = createProgram(gl, sh.v_bypixels, sh.f_sprite); 
    sh.sprite.u.res = gl.getUniformLocation(sh.sprite.p, "u_resolution"); 
    sh.sprite.u.img = gl.getUniformLocation(sh.sprite.p, 'u_image'); 
    sh.sprite.a.position = gl.getUniformLocation(sh.sprite.p, "a_position"); 
    sh.sprite.a.positionBuffer = gl.createBuffer(); 
    sh.sprite.a.texCoord = gl.getUniformLocation(sh.sprite.p, "a_texCoord"); 
    sh.sprite.a.texCoordBuffer = gl.createBuffer(); 
    gl.bindBuffer(gl.ARRAY_BUFFER, sh.sprite.a.texCoordBuffer); 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), gl.STATIC_DRAW); 

    cursor=createTexture("graphics/cursor.png",function() { renderStuff(); }); 
})(); 
</script> 
</body> 
</html> 

これは、白い空白の画面を表示します。私はそれがマウスの位置にテクスチャを表示することを望んでいた。コンソールなどにエラーはありません。それから私は周りを遊んで、私が説明できない奇妙な何かに気づいた。私はこれを私のフラグメントシェーダに追加しました:

if(v_texCoord==vec2(0.0,0.0)) gl_FragColor = vec4(1.0,0.0,0.0,1.0); 

実際、画像上のテクスチャ座標は明らかに0.0/0.0です。 WebGLは、スプライトの正確なサイズで、スプライトが想定される位置に赤いボックスを正しくレンダリングするようになりました。だから私の注意は、私がテクスチャ座標を渡すようにバッファを設定した部分になっていて、さらに奇妙なことが起きました。コードの周りをスワップして、位置バッファを最初に設定すると、(rendersprite関数):

gl.bindBuffer(gl.ARRAY_BUFFER, sh.sprite.a.positionBuffer); 
    gl.enableVertexAttribArray(sh.sprite.a.position); 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]), gl.STATIC_DRAW); 
    gl.vertexAttribPointer(sh.sprite.a.position, 2, gl.FLOAT, false, 0, 0); 
    gl.bindBuffer(gl.ARRAY_BUFFER, sh.sprite.a.texCoordBuffer); 
    gl.enableVertexAttribArray(sh.sprite.a.texCoord); 
    gl.vertexAttribPointer(sh.sprite.a.texCoord, 2, gl.FLOAT, false, 0, 0); 

今、私の赤いボックスはもはや存在しません!だから、何らかの理由で、私がこのシンプルなシェーダで最初に設定しているバッファは動作していませんが、何らかの理由でそれを見ることはできません。私はさまざまな方法で試してみました。私はまた、注文がなぜ重要であるかについても混乱しています。

誰でもご存知ですか?

答えて

1

getUniformLocationを使用して属性の場所を照会していますが、属性はユニフォームではなく、代わりにgetAttribLocationを使用して照会する必要があります。属性にgetUniformLocationを呼び出す

は、したがって、あなたが頂点同じ場所に属性を結合している、あなたのenableVertexAttribArrayvertexAttribPointer呼び出しで0にキャストされnullを返します。

sh.sprite.a.position = gl.getAttribLocation(sh.sprite.p, "a_position"); 
sh.sprite.a.positionBuffer = gl.createBuffer(); 
sh.sprite.a.texCoord = gl.getAttribLocation(sh.sprite.p, "a_texCoord"); 
sh.sprite.a.texCoordBuffer = gl.createBuffer(); 
+0

私はそれが本当に愚かな/明らかなものだろうと知っていました!ありがとう、私は問題を修正したので、正解とマークしています。 – Lars

関連する問題