2016-05-15 36 views
1

我目前正在嘗試使用WebGL渲染簡單的紋理。 這基本上是一個來自正常系統OpenGL的端口。 它似乎沒有工作,我真的不知道有什麼問題,因爲它似乎也很難調試這些東西。WebGL:簡單紋理渲染問題(「繪製到比視口矩形小的目標矩形」)

我雖然獲得在Firefox上的錯誤: 「錯誤:WebGL的:drawElements:繪製到目標矩形比視矩形小(該警告僅會被給予)。」

的視/投影矩陣/職位似乎是正確的,爲什麼我會得到那個錯誤?

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <title>Test</title> 
    <style> 
    .canstyle { 
    width: 800px; 
    height: 600px; 
    } 
    </style> 
</head> 
<body> 
    <canvas id="canvas0" class="canstyle"> 
    </canvas> 
    <script type='text/javascript'> 
    var vertexShaderSrc = ` 
      precision mediump float; 

      attribute vec2 aVertexPosition; 
      attribute vec2 aTextureCoord; 

      uniform mat3 projectionMatrix; 

      varying vec2 vTextureCoord; 

      void main() { 
       gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0); 
       vTextureCoord = aTextureCoord; 
      } 
    `; 

    var fragmentShaderSrc = ` 

      precision mediump float; 

      varying vec2 vTextureCoord; 

      uniform sampler2D uSampler; 

      void main() { 
      gl_FragColor = texture2D(uSampler, vTextureCoord); 
      } 
    `; 

    var img1 = new Image(); // HTML5 Constructor 
    img1.src = 'bunny.png'; 
    img1.alt = 'alt'; 
    img1.onload = function() { 
    render(); 
    } 

    function render() { 
    var canvas = document.getElementById("canvas0"); 
    var gl = canvas.getContext("webgl", { 
     alpha: false, 
     depth: false, 
     stencil: true, 
     premultipliedAlpha: false 
    }); 

    var funcs = Object.getOwnPropertyNames(gl.__proto__).filter(function(p) { 
     return typeof gl[p] === 'function'; 
    }); 

    function HookFunction(func, callback) { 
     return function() { 
     var res = func.apply(this, arguments); 
     callback(arguments); 
     return res; 
     }; 
    } 

    var endFrame = false; 
    var afterFrame = 8; 
    funcs.forEach(function(funcName) { 
     gl[funcName] = HookFunction(gl[funcName], function(args) { 
     if (endFrame) { 
      if (afterFrame == 0) { 
      return; 
      } 
      afterFrame -= 1; 
     } 
     if (funcName == "drawElements") { 
      endFrame = true; 
     } 
     var KK = []; 
     var dumpArr = []; 
     for (var item in args) { 
      var arg = args[item]; 
      if (arg === null) { 
      KK.push("null"); 
      } else if (arg instanceof ArrayBuffer || arg instanceof Float32Array || arg instanceof Uint8Array || arg instanceof Uint16Array) { 
      dumpArr.push(new Uint8Array(arg.buffer)); 
      } else { 
      KK.push(arg); 
      } 
     } 
     console.log("WebGL Interceptor: ", funcName, "(", KK.join(', '), ")"); 
     if (dumpArr.length) { 
      console.log(dumpArr); 
     } 

     }); 
    }); 

    gl.disable(gl.DEPTH_TEST); 
    gl.disable(gl.CULL_FACE); 
    gl.disable(gl.STENCIL_TEST); 
    gl.enable(gl.BLEND); 
    gl.enable(gl.SCISSOR_TEST); 

    gl.bindFramebuffer(gl.FRAMEBUFFER, null); 

    gl.viewport(0, 0, 800, 600); 
    gl.scissor(0, 0, 800, 600); 

    gl.clearColor(0.06274509803921569, 0.6, 0.7333333333333333, 1); 
    gl.clear(gl.COLOR_BUFFER_BIT); 

    var vertexDataCount = 4; 
    var vertexByteSize = vertexDataCount * 4; 
    var BatchSize = 2000; 

    var totalIndices = BatchSize * 6; 

    var vertices = new ArrayBuffer(BatchSize * vertexByteSize * 4); 
    var indices = new ArrayBuffer(totalIndices * 2); 

    var indicesUint16View = new Uint16Array(indices); 
    var verticesFloat32View = new Float32Array(vertices); 

    var j = 0; 
    for (var i = 0; i < totalIndices; i += 6, j += 4) { 
     indicesUint16View[i + 0] = j + 0; 
     indicesUint16View[i + 1] = j + 1; 
     indicesUint16View[i + 2] = j + 2; 
     indicesUint16View[i + 3] = j + 0; 
     indicesUint16View[i + 4] = j + 2; 
     indicesUint16View[i + 5] = j + 3; 
    } 

    var indexBuffer = gl.createBuffer(); 
    var vertexBuffer = gl.createBuffer(); 

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indicesUint16View, gl.STATIC_DRAW); 

    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); 
    gl.bufferData(gl.ARRAY_BUFFER, verticesFloat32View, gl.DYNAMIC_DRAW); 

    function compileShader(shaderSource, shaderType) { 
     var shader = gl.createShader(shaderType); 
     gl.shaderSource(shader, shaderSource); 
     gl.compileShader(shader); 
     var success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); 
     if (!success) { 
     throw "could not compile shader:" + gl.getShaderInfoLog(shader); 
     } 
     return shader; 
    } 

    function createProgram(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) { 
     throw ("program filed to link:" + gl.getProgramInfoLog(program)); 
     } 
     return program; 
    } 

    var vertexShad = compileShader(vertexShaderSrc, gl.VERTEX_SHADER); 
    var fragShad = compileShader(fragmentShaderSrc, gl.FRAGMENT_SHADER); 

    var shaderProg = createProgram(vertexShad, fragShad); 
    gl.useProgram(shaderProg); 

    var vertLoc = gl.getAttribLocation(shaderProg, "aVertexPosition"); 
    var texCoordLoc = gl.getAttribLocation(shaderProg, "aTextureCoord"); 

    gl.enableVertexAttribArray(vertLoc); 
    gl.enableVertexAttribArray(texCoordLoc); 

    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); 
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); 

    gl.vertexAttribPointer(vertLoc, 2, gl.FLOAT, false, vertexByteSize, 0); 
    gl.vertexAttribPointer(texCoordLoc, 2, gl.FLOAT, false, vertexByteSize, 2 * 4); 


    var currIndex = 0; 
    verticesFloat32View[currIndex++] = 174; // pos 
    verticesFloat32View[currIndex++] = 113; // pos 
    verticesFloat32View[currIndex++] = 0; // UV 
    verticesFloat32View[currIndex++] = 0; // UV 

    verticesFloat32View[currIndex++] = 226; // pos 
    verticesFloat32View[currIndex++] = 113; // pos 
    verticesFloat32View[currIndex++] = 1; // UV 
    verticesFloat32View[currIndex++] = 0; // UV 

    verticesFloat32View[currIndex++] = 226; // pos 
    verticesFloat32View[currIndex++] = 187; // pos 
    verticesFloat32View[currIndex++] = 1; // UV 
    verticesFloat32View[currIndex++] = 1; // UV 

    verticesFloat32View[currIndex++] = 174; // pos 
    verticesFloat32View[currIndex++] = 187; // pos 
    verticesFloat32View[currIndex++] = 0; // UV 
    verticesFloat32View[currIndex++] = 1; // UV 

    gl.bufferSubData(gl.ARRAY_BUFFER, 0, verticesFloat32View); 

    // | 2/Width | 0   | -1 
    // | 0   | 2/Height | -1 
    // | 0   | 0   | 1 
    var rawProjectionMat = new Float32Array([ 
     0.00249999994, 0, 0, 0, -0.00333333341, 0, -1, 1, 1 
    ]); 

    gl.uniformMatrix3fv(gl.getUniformLocation(shaderProg, "projectionMatrix"), false, rawProjectionMat); 

    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); 
    gl.activeTexture(gl.TEXTURE0); 

    var texture = gl.createTexture(); 
    gl.bindTexture(gl.TEXTURE_2D, 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.LINEAR); 
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 

    gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); 
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img1); 

    gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); 

    } 
    </script> 
</body> 
</html> 

編輯: 我用下面的圖片: https://raw.githubusercontent.com/pixijs/examples/gh-pages/_assets/bunny.png

+0

https://stackoverflow.com/questions/13441843/webgl-everything-is-blurry-despite-using-same-code – lled

回答

2

我只是猜測的問題是沒有你在哪裏設置你的canvas元素的內容的大小。

畫布元素中實際像素的數量默認爲300x150。您可以設置在HTML與

<canvas width="800" height="600"></canvas> 

,或者你可以用

​​

Firefox的設置在JavaScript中,你的視口設置爲800x600警告你,但它比你的畫布(300x150)更大,這是非常不尋常的,警告是幫助你注意到這個問題。

僅供參考:gl.viewport只做2件事。它設置從剪輯空間到屏幕空間(或者在這種情況下爲畫布空間)的轉換,並設置頂點的剪輯區域。 「裁剪頂點」意味着它不剪裁像素,因此在視口設置邊緣繪製一個gl_PointSize = 10.0點將在視口設置外繪製。

要剪輯像素,請使用剪式測試。我看到你正在進行剪刀測試,但由於你顯然想畫在畫布的邊緣,所以你根本不需要設置剪刀。

+0

如果我在一個頁面中有多個畫布,每個畫面只是一個部分,我該怎麼做那麼修復呢? – majidarif

+1

多個畫布可能不是一個好主意。瀏覽器限制了你可以擁有的數量,而且你不能在畫布之間共享資源(紋理,緩衝區)。相反,[這](http://stackoverflow.com/questions/30608723/is-it-possible-to-enable-unbounded-number-of-renderers-in-three-js/30633132#30633132),或類似的[這](http://twgljs.org/examples/itemlist.html) – gman

+0

第二個鏈接應該對我的使用很好,因爲每個畫布實際上是一個表格單元格。 – majidarif