我正在尝试使用gl_PointSize大的渲染很多点。如果位置不存在if [-1,1],则看起来顶点着色器将自动放弃gl.POINTS渲染。
在我的情况下,如果该点的位置稍微偏离[-1,1],则仍应在画布上显示该点的一部分。当位置不在[-1,1]之外时,是否可以让着色器保持渲染点?
这是在画布上一点位置绘制点的代码。但预计它将在画布上显示近一半。
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
var positions = [
-1.0001, -1
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
....
gl.enableVertexAttribArray(positionAttributeLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset);
gl.drawArrays(gl.POINTS, 0, 1);
在我的顶点着色器中,
....
gl_PointSize = 32.0;
....
答案 0 :(得分:0)
我无法重复您的问题。用POINTS在画布外面画图似乎很适合我
来自the OpenGL ES 2.0 spec第2.13节
如果所考虑的图元是一个点,则如果剪裁位于近或远剪裁平面之外,则剪裁会丢弃该点; 否则将保持不变。
您看到不同的结果吗?
当然,请注意,只有WebGL和OpenGL ES 2.0才需要支持最大点大小为1.0。看起来像most support at least 60
const gl = document.querySelector('canvas').getContext('webgl');
const vs = `
attribute vec4 position;
void main() {
gl_Position = position;
gl_PointSize = 64.0;
}
`;
const fs = `
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0, 0, 1);
}
`;
const program = twgl.createProgram(gl, [vs, fs]);
const positionLoc = gl.getAttribLocation(program, 'position');
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1.001, -1.001,
1.001, -1.001,
-1.001, 1.001,
1.001, 1.001,
0, 0,
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
gl.useProgram(program);
gl.drawArrays(gl.POINTS, 0, 5);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
<canvas></canvas>
根据this thread,这是OpenGL vs OpenGL ES的问题
OpenGL规范说
如果所考虑的图元是一个点,则如果剪裁位于剪裁区内,则剪裁会将其传递通过;否则,它将被丢弃。
它与OpenGL ES规范略有不同。 OpenGL可以有效地切中要点,OpenGL ES则不能。不过,甚至更奇怪的是,许多OpenGL驱动程序并没有像规范要求的那样进行裁剪。
那是它的简短版本,意味着您不能指望这些点是否在WebGL中没有被裁剪,因此您可能需要考虑绘制自己的四边形。您可以使顶点着色器将gl_PointSize
当前使用的值扩展为四边形,并使用GPU实例化或手动实例化绘制许多点。如果您使用GPU实例化,则对于每个POINT位置,就像现在一样,每个点有一个位置。如果您使用的是手动实例化,那么如果您不想在属性中重复这些位置,则需要为每个顶点重复该位置或添加一个点ID并将其放置在纹理中。
使用GPU实例化的示例
const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl');
const ext = gl.getExtension('ANGLE_instanced_arrays');
if (!ext) {
alert('need ANGLE_instanced_arrays');
}
const vs = `
attribute vec4 position; // center point
attribute vec2 cornerPosition; // the corners (-0.5 to 0.5)
uniform vec2 resolution;
varying vec3 pointCoord; // only if you need gl_PointCoord substitute
void main() {
// do the normal thing (can mult by matrix or whatever here
gl_Position = position;
float pointSize = 64.0;
// -- point emulation
gl_Position.xy += cornerPosition * (pointSize * 2.0 - 1.0) /
resolution * gl_Position.w;
// only if you need gl_PointCoord substitute
pointCoord = vec3(cornerPosition * 0.5, gl_Position.z);
}
`;
const fs = `
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0, 0, 1);
}
`;
const programInfo = twgl.createProgram(gl, [vs, fs]);
const program = twgl.createProgram(gl, [vs, fs]);
const positionLoc = gl.getAttribLocation(program, 'position');
const cornerPositionLoc = gl.getAttribLocation(program, 'cornerPosition');
const resolutionLoc = gl.getUniformLocation(program, 'resolution');
{
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-1.001, -1.001,
1.001, -1.001,
-1.001, 1.001,
1.001, 1.001,
0, 0,
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
ext.vertexAttribDivisorANGLE(positionLoc, 1);
}
{
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
-0.5, 0.5,
0.5, -0.5,
0.5, 0.5,
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(cornerPositionLoc);
gl.vertexAttribPointer(cornerPositionLoc, 2, gl.FLOAT, false, 0, 0);
}
gl.useProgram(program);
gl.uniform2f(resolutionLoc, gl.canvas.width, gl.canvas.height);
ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, 5); // 5 points, 6 verts per point
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>
您应该看到它创建与上面相同的图像。它的优点是不受点大小限制,并且可以解决驱动程序错误。在您自己的硬件上进行测试,看看是否可以解决您的问题。
请记住,如果不使用顶点数组对象,则可能需要在尝试渲染其他对象之前将属性除数重置为零。
ext.vertexAttribDivisorANGLE(positionLoc, 0);
还有一个例子可以测试
const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl');
const ext = gl.getExtension('ANGLE_instanced_arrays');
if (!ext) {
alert('need ANGLE_instanced_arrays');
}
const vs = `
attribute vec4 position; // center point
attribute vec2 cornerPosition; // the corners (-0.5 to 0.5)
uniform vec2 resolution;
uniform mat4 matrix;
varying vec3 pointCoord; // only if you need gl_PointCoord substitute
void main() {
// do the normal thing (can mult by matrix or whatever here
gl_Position = matrix * position;
float pointSize = 20.0 / gl_Position.w;
// -- point emulation
gl_Position.xy += cornerPosition * (pointSize * 2.0 - 1.0) /
resolution * gl_Position.w;
// only if you need gl_PointCoord substitute
pointCoord = vec3(cornerPosition * 0.5, gl_Position.z);
}
`;
const fs = `
precision mediump float;
void main() {
gl_FragColor = vec4(1, 0, 0, 1);
}
`;
const programInfo = twgl.createProgram(gl, [vs, fs]);
const program = twgl.createProgram(gl, [vs, fs]);
const positionLoc = gl.getAttribLocation(program, 'position');
const cornerPositionLoc = gl.getAttribLocation(program, 'cornerPosition');
const resolutionLoc = gl.getUniformLocation(program, 'resolution');
const matrixLoc = gl.getUniformLocation(program, 'matrix');
const numPoints = 100;
{
// adapted from http://stackoverflow.com/a/26127012/128511
function fibonacciSphere(samples, i) {
const rnd = 1.;
const offset = 2. / samples;
const increment = Math.PI * (3. - Math.sqrt(5.));
// for i in range(samples):
const y = ((i * offset) - 1.) + (offset / 2.);
const r = Math.sqrt(1. - Math.pow(y ,2.));
const phi = (i + rnd % samples) * increment;
const x = Math.cos(phi) * r;
const z = Math.sin(phi) * r;
return [x, y, z];
}
const positions = [];
for (let i = 0; i < numPoints; ++i) {
positions.push(...fibonacciSphere(numPoints, i));
}
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 3, gl.FLOAT, false, 0, 0);
ext.vertexAttribDivisorANGLE(positionLoc, 1);
}
{
const buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
-0.5, -0.5,
0.5, -0.5,
-0.5, 0.5,
-0.5, 0.5,
0.5, -0.5,
0.5, 0.5,
]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(cornerPositionLoc);
gl.vertexAttribPointer(cornerPositionLoc, 2, gl.FLOAT, false, 0, 0);
}
function render(ms) {
const secs = ms * 0.001;
const mat = m4.perspective(
60 * Math.PI / 180,
gl.canvas.clientWidth / gl.canvas.clientHeight,
0.1,
100);
m4.translate(mat, [0, 0, -2.11 + Math.sin(secs)], mat);
m4.rotateX(mat, secs, mat);
m4.rotateY(mat, secs * 0.93, mat);
gl.useProgram(program);
gl.uniform2f(resolutionLoc, gl.canvas.width, gl.canvas.height);
gl.uniformMatrix4fv(matrixLoc, false, mat);
// 6 verts per point
ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, numPoints);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>