2016-02-16 3 views
6

Tavares WebGL tutorialで作業していて、泥の中で立ち往生しています。GL.pointsを使用してWebGLで単一のピクセルを描画します

GL.pointsを使用して1つのピクセルを描画します。私の配列には何かが間違っています。 FFやChromeカナリアでください:

http://codepen.io/anon/pen/EPJVjK

/** 
* Creates a program, attaches shaders, links the program. 
* @param {WebGLShader[]} shaders. The shaders to attach. 
*/ 
var createGLProgram = function(gl, shaders) { 
    var program = gl.createProgram(); 
    for (var i = 0; i < shaders.length; i += 1) { 
     gl.attachShader(program, shaders[ i ]); 
    } 

    gl.linkProgram(program); 

    // Check the link status 
    var linked = gl.getProgramParameter(program, gl.LINK_STATUS); 
    if (!linked) { 

     // Something went wrong with the link 
     var lastError = gl.getProgramInfoLog(program); 
     window.console.error("Error in program linking: " + lastError); 

     gl.deleteProgram(program); 
     return null; 
    } 
    return program; 
}; 

var myCreateShader = function(gl, shaderScriptText, shaderType) { 

    // Create the shader object 
    var shader = gl.createShader(shaderType); 

    // Load the shader source 
    gl.shaderSource(shader, shaderScriptText); 

    // Compile the shader 
    gl.compileShader(shader); 
    return shader; 
}; 

// Get A WebGL context. 
var canvas = document.getElementById("canvas"); 

var gl = canvas.getContext("webgl", { antialias: false }) 

var vertexShader = myCreateShader(gl, 
    `attribute vec2 a_position; 

    uniform vec2 u_resolution; 

    void main() { 
    // convert the rectangle from pixels to 0.0 to 1.0 
     vec2 zeroToOne = a_position/u_resolution; 

     // convert from 0 -> 1 to 0 -> 2 
     vec2 zeroToTwo = zeroToOne * 2.0; 

     // convert from 0 -> 2 to -1 -> +1 (clipspace) 
     vec2 clipSpace = zeroToTwo - 1.0; 

     // Flip 0,0 from bottom left to conventional 2D top left. 
     gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); 
    }`, gl.VERTEX_SHADER); 

var fragmentShader = myCreateShader(gl, 
    `precision mediump float; 

    uniform vec4 u_color; 

    void main() { 
    gl_FragColor = u_color; 
    }`, gl.FRAGMENT_SHADER); 

var program = createGLProgram(gl, [ vertexShader, fragmentShader ]); 
gl.useProgram(program); 

// Store color location. 
var colorLocation = gl.getUniformLocation(program, "u_color"); 

// Look up where the vertex data needs to go. 
var positionLocation = gl.getAttribLocation(program, "a_position"); 

// Set the resolution. 
var resolutionLocation = gl.getUniformLocation(program, "u_resolution"); 
gl.uniform2f(resolutionLocation, canvas.width, canvas.height); 

// Create a buffer. 
var buffer = gl.createBuffer(); 
gl.bindBuffer(gl.ARRAY_BUFFER, buffer); 
gl.enableVertexAttribArray(positionLocation); 

// Send the vertex data to the shader program. 
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0); 

// Set color to black. 
gl.uniform4f(colorLocation, 0, 0, 0, 1); 

function drawOneBlackPixel(gl, x, y) { 
    // Fills the buffer with a single point? 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 
     x,  y, 
      0,  y, 
      x,  0, 
      x,  0, 
      0,  y, 
      0,  0]), gl.STATIC_DRAW); 

    // Draw one point. 
    gl.drawArrays(gl.POINTS, 0, 1); 
} 


// These tests are supposed to be x,y coordinates from top left. 
drawOneBlackPixel(gl, 0, 0); 
drawOneBlackPixel(gl, 1, 1); 
drawOneBlackPixel(gl, 2, 2); 
drawOneBlackPixel(gl, 3, 3); 
drawOneBlackPixel(gl, 4, 4); 
drawOneBlackPixel(gl, 5, 5); 
drawOneBlackPixel(gl, 6, 6); 
drawOneBlackPixel(gl, 7, 7); 
drawOneBlackPixel(gl, 10, 5); 
drawOneBlackPixel(gl, 15, 5); 
drawOneBlackPixel(gl, 20, 5); 
drawOneBlackPixel(gl, 12, 34); 
drawOneBlackPixel(gl, 42, 42); 

の問題は、画素が所定の位置に非常にレンダリングされていないということです。 (0,0)は左上隅にペイントしません。そして、ピクセルの対角線であるべきであるものは、代わりに2ピクセルのチャンクで「踏み込まれた」ものです。働くCodepenは理想的でしょう。

第2の「ボーナス」の質問として、​​で呼び出されたdrawArraysコールで複数のピクセルをバッチすることができます。最善を尽くす方法についての助言は大いに感謝しています。

P.S.私は読んだ:

How can I set the color of a pixel on a canvas using WebGL?

が、私の誤差は多少それよりも低いレベルのようです。そして、私にcanvas2Dの使用を勧めないでください。私はWebGLののパフォーマンスをしたい、と私は:)

+0

チュートリアルをお読みください。その頂点シェーダはいくつかのステップで記述されていますが、後でいくつかの記事が圧縮されて1つのラインになり、はるかに柔軟です – gman

答えて

7

地面からいくつかのことを学ぶしようとしている:あなたはgl.POINTのサイズをWebGLの伝えるためにあなたの頂点シェーダにgl_PointSize = 1.0;を追加する必要が

ファーストを。

第二に、あなたが渡す座標は、各画素の中央あるのではなく、各ピクセルの左上隅にある、したがって、

function drawOneBlackPixel(gl, x, y) { 
    // Fills the buffer with a single point? 
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 
     x+0.5,  y+0.5]), gl.STATIC_DRAW); 

    // Draw one point. 
    gl.drawArrays(gl.POINTS, 0, 1); 
} 

は、あなたが望むものです。

ここにワーキングコデック:http://codepen.io/anon/pen/pgBjBy

ボーナスの質問:gl.buffer(gasp)の手動メモリ管理が必要なので、gl.drawArrays(gl.POINTS, 0, x);でxポイントを描くことができます。たとえば、(0,0)(1,1)、(2,2)に3つの点を描画する場合は、

たとえば、最初にFloat32Arrayを部屋に4点を入れると、drawOneBlackPixelと呼ぶたびにFloat32Arrayを最初に[p1x、p1y、0,0,0,0,0,0]に設定し、次にdrawOneBlackPixelに配列を[p1x、p1y、p2x 、p2y、0,0,0,0]などとする。もちろん、必要に応じてFloat32Arrayを拡張したりコピーしたり、変更を加えるときにFloat32ArrayをGPUにアップロードしたりするなど、他の処理を行う必要があります。どのようにポイントの「消去」を処理するかは、心に留めておくべきことです。

関連する問題