2016-07-05 77 views
4

我想用WebGL繪製一個像素。我正在使用gl_PointSize = 1.0gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0)。我預計單個黑色像素。然而,這是我的觀點的呈現方式:如何在webgl上使用`gl.POINTS`繪製單個像素?

enter image description here

也就是說,我得到的是灰色的點佔地約3×3的區域。我如何得到實際的單個像素?

回答

3

首先,您的畫布尺寸是否與顯示尺寸1x1像素相匹配?如果沒有,你會得到拉伸像素。 Canvases have 2 sizes。 drawingBuffer的大小和顯示的大小。 CSS設置它們顯示的大小。它們的寬度和高度設置了drawingBuffer的大小。

GL中的第二個像素由它們的邊緣尋址。換句話說,假設您有3x1像素畫布。有3個像素

-1,1        1,1 
    +----------+----------+----------+ 
    |   |   |   | 
    |   |   |   | 
    |   |   |   | 
    |   |   |   | 
    +----------+----------+----------+ 
-1,-1        1,-1 

要繪製第一個像素,你需要給它的中心點。在上圖中,第一個像素的中心點是

 -2/3,0 

讓我們試試吧。下面的代碼行將3X1像素的紋理然後繪製紋理到300x100的畫布,所以我們可以清楚地看到它

'use strict'; 
 

 
var vs_point = ` 
 
attribute vec4 position; 
 
void main() { 
 
    gl_Position = position; 
 
    gl_PointSize = 1.0; 
 
} 
 
`; 
 
var fs_point = ` 
 
precision mediump float; 
 
void main() { 
 
    gl_FragColor = vec4(0, 0, 0, 1); 
 
}`; 
 

 
var vs_tex = ` 
 
attribute vec4 position; 
 
varying vec2 v_texcoord; 
 
void main() { 
 
    gl_Position = position; 
 
    v_texcoord = position.xy * 0.5 + 0.5; 
 
} 
 
`; 
 
var fs_tex = ` 
 
precision mediump float; 
 
uniform sampler2D u_texture; 
 
varying vec2 v_texcoord; 
 
void main() { 
 
    gl_FragColor = texture2D(u_texture, v_texcoord); 
 
} 
 
`; 
 

 
// Let's make a 3x1 texture, render to it 
 
// then render it to the canvas with gl.NEAREST 
 
var canvas = document.querySelector("canvas"); 
 
var gl = canvas.getContext("webgl"); 
 
var pointProgramInfo = twgl.createProgramInfo(
 
    gl, [vs_point, fs_point]); 
 
var texProgramInfo = twgl.createProgramInfo(
 
    gl, [vs_tex, fs_tex]); 
 

 
var pointBufferInfo = twgl.createBufferInfoFromArrays(gl, { 
 
    position: { numComponents: 2, data: [ -2/3, 0 ] }, 
 
}); 
 
var quadBufferInfo = twgl.primitives.createXYQuadBufferInfo(gl); 
 
    
 
// make a 3x1 pixel texture and attach to framebuffer 
 
var framebufferInfo = twgl.createFramebufferInfo(gl, [ 
 
    { format: gl.RGBA, mag: gl.NEAREST, min: gl.NEAREST, wrap: gl.CLAMP_TO_EDGE, } 
 
], 3, 1); 
 

 
// draw 1 pixel into texture 
 
twgl.bindFramebufferInfo(gl, framebufferInfo); 
 
gl.useProgram(pointProgramInfo.program); 
 
twgl.setBuffersAndAttributes(gl, pointProgramInfo, pointBufferInfo); 
 
twgl.drawBufferInfo(gl, gl.POINTS, pointBufferInfo); 
 
    
 
// put in a clipspace quad 
 
twgl.bindFramebufferInfo(gl, null); 
 
gl.useProgram(texProgramInfo.program); 
 
twgl.setBuffersAndAttributes(gl, texProgramInfo, quadBufferInfo); 
 
twgl.drawBufferInfo(gl, gl.TRIANGLES, quadBufferInfo); 
 
canvas { border: 1px solid red; }
<script src="https://twgljs.org/dist/twgl-full.min.js"></script> 
 
<canvas width="300" height="100"></canvas>

或作爲另一個例子,讓我們畫隨機像素的畫布。

的重要組成部分,是一個像素的位置是

clipspaceX = (x + 0.5)/destWidth * 2 - 1; 
clipspaceY = (y + 0.5)/destHeight * 2 - 1; 

'use strict'; 
 

 
var vs = ` 
 
attribute vec4 position; 
 
void main() { 
 
    gl_Position = position; 
 
    gl_PointSize = 1.0; 
 
} 
 
`; 
 
var fs = ` 
 
precision mediump float; 
 
uniform vec4 u_color; 
 
void main() { 
 
    gl_FragColor = u_color; 
 
}`; 
 

 
var canvas = document.querySelector("canvas"); 
 
var gl = canvas.getContext("webgl", {preserveDrawingBuffer: true}); 
 

 
// make canvas 1x1 with display 
 
gl.canvas.width = gl.canvas.clientWidth * window.devicePixelRatio; 
 
gl.canvas.height = gl.canvas.clientHeight * window.devicePixelRatio; 
 
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 
 

 
var programInfo = twgl.createProgramInfo(gl, [vs, fs]); 
 

 
var positions = new Float32Array(2000); 
 
var bufferInfo = twgl.createBufferInfoFromArrays(gl, { 
 
    position: { numComponents: 2, data: positions, }, 
 
}); 
 

 
gl.useProgram(programInfo.program); 
 
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo); 
 

 
function randInt(max) { 
 
    return Math.random() * max | 0; 
 
} 
 

 
var offset = [0, 0]; 
 
var color = [0, 0, 0, 1]; 
 

 
var uniforms = { 
 
    u_offset: offset, 
 
    u_color: color, 
 
}; 
 

 
function render() { 
 
    var length = positions.length; 
 
    for (var i = 0; i < length; i += 2) { 
 
    var x = randInt(gl.canvas.width); 
 
    var y = randInt(gl.canvas.height); 
 

 
    positions[i + 0] = (x + 0.5)/gl.canvas.width * 2 - 1; 
 
    positions[i + 1] = (y + 0.5)/gl.canvas.height * 2 - 1; 
 
    } 
 
    twgl.setAttribInfoBufferFromArray(
 
    gl, bufferInfo.attribs.position, positions); 
 
    
 
    var cndx = randInt(3); 
 
    color[cndx] = 1; 
 
    color[(cndx + 1) % 3] = 0; 
 

 
    twgl.setUniforms(programInfo, uniforms); 
 
    twgl.drawBufferInfo(gl, gl.POINTS, bufferInfo); 
 
    
 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/twgl-full.min.js"></script> 
 
<canvas style="width:300px; height:150px;"></canvas>