使用 GL.points 在 WebGL 中绘制单个像素
Draw a single pixel in WebGL using GL.points
我正在学习Tavares WebGL教程,并陷入泥潭。
我想使用 GL.points
绘制单个像素。我的阵列显然有问题。请参阅FF或Chrome Canary:
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( 不会在左上角绘制。而应该是像素的对角线反而被"阶梯"成两个像素的块。一个工作的代码笔将是理想的。
作为第二个"奖励"问题,我接下来希望能够在单个drawArrays
调用上批处理多个像素,在requestAnimationFrame
上调用。关于如何最好地做到这一点的建议将不胜感激。
附言我读过:
如何使用 WebGL 在画布上设置像素的颜色?
但我的错误似乎比这低一些。请不要建议我使用canvas2D。我想要webGL的性能,我正在尝试从头开始学习:)
几件事:
首先,您需要向顶点着色器添加gl_PointSize = 1.0;
以告诉 webgl 您的gl.POINT
的大小。
其次,您传入的坐标是每个像素的中心,而不是每个像素的左上角,因此,
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
(喘息(,以便您可以gl.drawArrays( gl.POINTS, 0, x );
绘制 x 点。例如,如果您想在 (0,0( (1,1(、(2,2( 处绘制 3 个点,那么您需要执行gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.5, 0.5, 1.5, 1.5, 2.5, 2.5], gl.STATIC_DRAW)
然后gl.drawArrays(gl.POINTS, 0, 3);
例如,您可以先分配一个具有 4 点空间的 Float32Array,然后在调用drawOneBlackPixel
时,它会首先将 Float32Array 设置为 [p1x,p1y,0,0,0,0,0,0,0],在接下来的drawOneBlackPixel
它将数组设置为 [p1x,p1y,p2x,p2y,0,0,0,0] 等等。当然,您必须处理其他事情,例如根据需要增长和复制 Float32Array,并在进行更改时将 Float32Array 上传到 GPU。如何处理积分的"擦除"也是要牢记的事情。
- D3在一个调用中绘制不同的SVG形状,没有可见性
- Javascript,有没有一种方法可以将数组写成没有逗号或空格的单个文本字符串
- 如何使用javascript获取嵌套对象中所有子对象的单个属性
- 是否可以禁用jquery中的单个单选按钮
- 有没有一个javascript图形绘制库可以进行气球树布局
- 引导程序:在导航栏中,显示悬停在单个位置的基于Li Link的不同内容
- 使用相同的数据集绘制各种符号
- 使用onclick绘制SVG路径
- 在谷歌地图上绘制位置数据库
- 用chart.js绘制条形图
- 使用jquery选中/取消选中单个复选框
- “可绘制地图”设置地图选项“纬度-经度”
- 单个页面上有多个标记表单
- 在不破坏未定义函数的情况下,对多个视图使用单个js文件
- 从 JSON 在单个高图表图中绘制多个序列
- 使用 GL.points 在 WebGL 中绘制单个像素
- d3 -如何调整从完整的美国clipPath绘制的单个州地图的大小
- 使用单个画布,我用javascript绘制了两个不同的图表,是否有任何方法可以在画布中删除最后绘制的图表
- 在单个页面上绘制多个画布
- 是否有一种方法可以在SVG文本路径上的单个字母周围绘制矩形