2016-07-05 44 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>