2016-07-05 21 views
4

Ich versuche, ein einzelnes Pixel mit WebGL zu zeichnen. Ich verwende gl_PointSize = 1.0 und gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0). Ich habe einzelne schwarze Pixel erwartet. Doch dies ist, wie meine Punkte gemacht werden:Wie zeichne ich ein einzelnes Pixel mit `gl.POINTS` auf webgl?

enter image description here

Das heißt, was ich bekomme, sind Punkte grau eine Fläche von ca. 3x3 bedeckt. Wie bekomme ich eigentlich einzelne Pixel?

Antwort

3

Zunächst entspricht die Größe Ihrer Leinwand der Displaygröße 1x1 Pixel? Wenn nicht, werden Sie gestreckte Pixel erhalten. Canvases have 2 sizes. Die Größe ihres drawingBuffers und die Größe, in der sie angezeigt werden. CSS legt die Größe fest, in der sie angezeigt werden. Ihre Breite und Höhe bestimmen die Größe des drawingBuffer.

Zweite Pixel im GL werden durch ihre Kanten adressiert. Mit anderen Worten, Sie haben 3x1 Pixel Canvas. Es gibt die 3 Pixel

Um das erste Pixel zu zeichnen, müssen Sie seinen Mittelpunkt geben. Im obigen Diagramm ist der Mittelpunkt des ersten Pixels

 -2/3,0 

Lassen Sie es uns versuchen. Der Code wird unten auf ein 3x1 Pixel-Textur zieht dann die Textur auf eine 300x100 Leinwand so können wir es

'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>

Oder als weiteres Beispiel wollen wir ziehen zufällige Pixel auf einer Leinwand deutlich sehen.

Der wichtigste Teil ist die Position eines Pixels

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>

Verwandte Themen