Is it possible to read from texture A and write to texture B that both use the same FBO? I don't believe this has been covered here already. Someone asked the question about OpenGL, but not about WebGL. It seems like the answer is no, based on the answer to this post, but if someone could tell me definitively whether reading/writing to textures in the same fbo is possible it'd really help me. In my code I get the following error:
WebGL warning: drawElementsInstanced: Texture level 0 would be read by TEXTURE_2D unit 0, but written by framebuffer attachment COLOR_ATTACHMENT1, which would be illegal feedback.
the following snippet generates an 'illegal feedback' warning. I know the code may not look/be useful but the point is accomplishing the read/write. To sumarize what I expect to happen is textureA (or call it texture 1) should be used to render to texture B ( aka texture 2 ). I should then see something on the screen; mostly likely 4 greed squares:
/* YOU CAN PROBABLY IGNORE THIS AS IT'S INITIALIZATION CODE */
const canvas = document.querySelector('canvas');
const gl = canvas.getContext('webgl2');
var fb;
var textures = [];
var tex_datei1 = new Array( 4*64*64 ).fill(9);
var vbo = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER , vbo );
var vertices = new Array( 4*64*64 ).fill( 0 );
gl.bindBuffer( gl.ARRAY_BUFFER , vbo );
gl.bufferData( gl.ARRAY_BUFFER , new Float32Array( vertices ) , gl.STATIC_DRAW );
var ibo = gl.createBuffer();
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER , ibo );
var indices = [ ...Array( vertices.length/4 ).keys() ];
indices[0] = 0;
indices[1] = 1;
indices[2] = 2;
indices[3] = 2;
indices[4] = 3;
indices[5] = 1;
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW);
var vc = `#version 300 es
precision mediump float;
uniform sampler2D u_image0;
uniform sampler2D u_image1;
in vec3 coordinates;
void main(void) {
float x = coordinates.x;
float y = coordinates.y;
vec4 sample_A = texture( u_image0 , vec2( x , y ) );
sample_A.x *= 64.0 * 4.0;
sample_A.y *= 64.0 * 4.0;
gl_Position = vec4( sample_A.x/10.0 , sample_A.y/10.0 , 0.0 , 1.0 );
gl_PointSize = 30.0;
}
`;
var vs = gl.createShader( gl.VERTEX_SHADER );
gl.shaderSource( vs , vc );
gl.compileShader(vs);
if( !gl.getShaderParameter( vs , gl.COMPILE_STATUS ) ){
console.log( gl.COMPILE_STATUS );
console.log( gl.getShaderInfoLog(vs) );
}
var fc = `#version 300 es
precision highp float;
out vec4 color;
void main(void) {
color = vec4( 0.5 , 0.5 , 0.0 , 1.0 );
}
`;
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, fc);
gl.compileShader(fs);
if( !gl.getShaderParameter( fs , gl.COMPILE_STATUS ) ){
console.log( gl.COMPILE_STATUS );
console.log( gl.getShaderInfoLog(fs) );
}
var program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
gl.useProgram( program);
var coordinates_u_loc = gl.getAttribLocation(program, "coordinates");
var u_image0_loc = gl.getUniformLocation( program , "u_image0");
var die_berechnung_u_image1Location = gl.getUniformLocation( program , "u_image1");
gl.bindBuffer( gl.ARRAY_BUFFER , vbo );
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER , ibo );
gl.enableVertexAttribArray( coordinates_u_loc );
gl.vertexAttribPointer( coordinates_u_loc , 4 , gl.FLOAT , false , 0 , 0 );
/* HERE IS WHERE I GET INTO FRAMEBUFFER SETUP */
fb = gl.createFramebuffer();
gl.bindFramebuffer( gl.FRAMEBUFFER , fb );
gl.uniform1i( u_image0_loc , 0);
//gl.uniform1i( u_image1_loc , 1);
var internal_formats = [ gl.RGBA , gl.RGBA ];
var formats = [ gl.RGBA , gl.RGBA ];
var types = [ gl.UNSIGNED_BYTE , gl.UNSIGNED_BYTE ];
var datas = [ new Uint8Array( tex_datei1.slice() ) , new Uint8Array( tex_datei1.slice() ) ];
for( var i = 0 ; i < datas.length ; i++ ){
var texture = gl.createTexture();
gl.bindTexture( gl.TEXTURE_2D , texture );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
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.texImage2D( gl.TEXTURE_2D ,
0 ,
internal_formats[i] ,
64 ,
64 ,
0 ,
formats[ i ] ,
types[ i ] ,
datas[ i ]
);
textures.push( texture );
}
/* HERE MAY LIE MY ISSUE AS I HAVE NO IDEA HOW TO SPECIFY THAT THE SECOND TEXTURE SHOULD BE WRITTEN TO. I'VE TRIED MESSING AROUND WITH THE LAYERS PARAMETER BUT THAT JUST CREATES MIPS ISSUES. */
gl.bindTexture( gl.TEXTURE_2D , textures[ 0 ] );
var attachmentPoint = gl.COLOR_ATTACHMENT0;
gl.framebufferTexture2D( gl.FRAMEBUFFER , attachmentPoint , gl.TEXTURE_2D , textures[ 0 ] , 0 );
gl.bindTexture( gl.TEXTURE_2D , textures[ 1 ] );
var attachmentPoint = gl.COLOR_ATTACHMENT1;
gl.framebufferTexture2D( gl.FRAMEBUFFER , attachmentPoint , gl.TEXTURE_2D , textures[ 1 ] , 0 );
var er = gl.checkFramebufferStatus( gl.FRAMEBUFFER );
if( er !== 36053 ){
console.log( er );
}
/* DRAW */
gl.clearColor( 0.0 , 0.0 , 0.0 , 0.0 );
gl.enable( gl.DEPTH_TEST );
gl.clear( gl.COLOR_BUFFER_BIT );
gl.viewport( 0,0, 64 , 64 );
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, textures[1] );
gl.drawElements( gl.POINTS , indices.length , gl.UNSIGNED_SHORT , 0 );
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<body>
<canvas width="64" heigh="64" style="width:64px; height:64px; border:thick solid #0000FF; "></canvas>
</body>
</html>