WebGL - пропустить значения после чтения из текстуры - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь реализовать простую программу, которая пишет в текстуру, а затем читает из нее на основе этого поста . Я ожидал получить массив значений от 0 до 99, вместо этого я получаю вывод фрагмента кода ниже, который пропускает значения, такие как 4,5,6,7 и добавляет дополнительные 0.

Почему я иногда имеют пропущенные значения и те 0, и что я могу сделать, чтобы решить эту проблему?

Ожидается:

[0,1,2,3,4,5,6,7,8, ... 97,98,99]

Вывод:

const gl = document.createElement("canvas").getContext("webgl");
const vs = `
attribute vec4 position;
attribute vec2 texcoord;

varying vec2 v_texcoord;

void main() {
  gl_Position = position;
  v_texcoord = texcoord;
}
`;

const fs = `
precision highp float;
uniform sampler2D u_srcData;
uniform float u_add;

varying vec2 v_texcoord;

void main() {
  vec4 value = texture2D(u_srcData, v_texcoord);
  
  // We can't choose the destination here. 
  // It has already been decided by however
  // we asked WebGL to rasterize.
  gl_FragColor = value + u_add;
}
`;

const program = buildProgram(vs,fs)

const size = 100;
// Uint8Array values default to 0
const srcData = new Uint8Array(size);
// let's use slight more interesting numbers
for (let i = 0; i < size; ++i) {
  srcData[i] = i;
}
//console.log('srcData:')
//console.log(srcData)


// Put that data in a texture. NOTE: Textures
// are (generally) 2 dimensional and have a limit
// on their dimensions. That means you can't make
// a 1000000 by 1 texture. Most GPUs limit from
// between 2048 to 16384.
// In our case we're doing 10000 so we could use
// a 100x100 texture. Except that WebGL can
// process 4 values at a time (red, green, blue, alpha)
// so a 50x50 will give us 10000 values
const srcTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, srcTex);
const level = 0;
const width = Math.sqrt(size / 4);
if (width % 1 !== 0) {
  // we need some other technique to fit
  // our data into a texture.
  alert('size does not have integer square root');
}
const height = width;
const border = 0;
const internalFormat = gl.RGBA;
const format = gl.RGBA;
const type = gl.UNSIGNED_BYTE;
gl.texImage2D(
  gl.TEXTURE_2D, level, internalFormat,
  width, height, border, format, type, srcData);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  
// create a destination texture
const dstTex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, dstTex);
gl.texImage2D(
  gl.TEXTURE_2D, level, internalFormat,
  width, height, border, format, type, null);

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);

// make a framebuffer so we can render to the
// destination texture
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
// and attach the destination texture
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, dstTex, level);

gl.useProgram(program)


var data = [
	//x,y,texX,texY
		-1,-1,0,0,
		.1,-1,1,0,
		-1,1,0,1,
		-1,1,0,1,
		1,-1,1,0,
		1,1,1,1,
	]
	

// buffer
const positionBuffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER,positionBuffer)
gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(data),gl.STATIC_DRAW)

// pointer
const positionLoc = gl.getAttribLocation(program,'position')
gl.vertexAttribPointer(
	positionLoc,
	2,
	gl.FLOAT,
	0,
	4*Float32Array.BYTES_PER_ELEMENT,
	0*Float32Array.BYTES_PER_ELEMENT
)
gl.enableVertexAttribArray(positionLoc)

const texcoordLoc = gl.getAttribLocation(program,'texcoord')
gl.vertexAttribPointer(
	texcoordLoc,
	2,
	gl.FLOAT,
	0,
	4*Float32Array.BYTES_PER_ELEMENT,
	2*Float32Array.BYTES_PER_ELEMENT
)
gl.enableVertexAttribArray(texcoordLoc)


// gl.activeTexture(gl.TEXTURE0)
gl.bindTexture(gl.TEXTURE_2D,srcTex)
gl.uniform1f(gl.getUniformLocation(program,'u_add'), 0 / 255)
gl.uniform1i(gl.getUniformLocation(program,'u_srcData'),0)



// set the viewport to match the destination size
gl.viewport(0, 0, width, height);

// draw the quad (2 triangles)
const offset = 0;
const numVertices = 6;
gl.drawArrays(gl.TRIANGLES, offset, numVertices);

// pull out the result
const dstData = new Uint8Array(size);
gl.readPixels(0, 0, width, height, format, type, dstData);

console.log('dstData:');
console.log(dstData);


// FUNCTIONS
function buildShader(type,source){
	const shader = gl.createShader(type)
	gl.shaderSource(shader,source)
	gl.compileShader(shader)

	if(!gl.getShaderParameter(shader,gl.COMPILE_STATUS)){
		throw new Error('ERROR compiling shader type '+type+' Info: '+gl.getShaderInfoLog(shader))
	}
	return shader
}

function buildProgram(vs,fs){
	const program = gl.createProgram()
	gl.attachShader(program,buildShader(gl.VERTEX_SHADER,vs))
	gl.attachShader(program,buildShader(gl.FRAGMENT_SHADER,fs))
	gl.linkProgram(program)
	gl.validateProgram(program)

	if(!gl.getProgramParameter(program,gl.LINK_STATUS)){
		throw new Error('ERROR: linking program. Info: '+gl.getProgramInfoLog(program))
	}
	if(!gl.getProgramParameter(program,gl.VALIDATE_STATUS)){
		throw new Error('ERROR: validating program. Info: '+gl.getProgramInfoLog(program))
	}
	return program
}

1 Ответ

0 голосов
/ 31 марта 2020

Как указал гман, у .1 вместо 1 в data.

...