WebGL Feedback Loop Warning: Texture Read-Write Conflict in p5.js Shader Rendering
nakednous opened this issue · 2 comments
nakednous commented
Most appropriate sub-area of p5.js?
- Accessibility
- Color
- Core/Environment/Rendering
- Data
- DOM
- Events
- Image
- IO
- Math
- Typography
- Utilities
- WebGL
- Build process
- Unit testing
- Internationalization
- Friendly errors
- Other (specify if possible)
p5.js version
1.9.2
Web browser and version
Mozilla firefox for archlinux. 124.0.1 (64-bit)
Operating system
Linux
Steps to reproduce this
Steps:
- Run the Snippet below.
texture(fbo.color)
triggers this error message:WebGL warning: drawElementsInstanced: Texture level 0 would be read by TEXTURE_2D unit 2, but written by framebuffer attachment COLOR_ATTACHMENT0, which would be illegal feedback. 32 After reporting 32, no further warnings will be reported for this WebGL context.
- The texture is rendered only once but doesn't get updated.
Snippet:
const uvVert = `precision highp float;
attribute vec3 aPosition;
attribute vec2 aTexCoord;
varying vec2 texcoords2;
void main() {
texcoords2 = aTexCoord;
gl_Position = vec4(aPosition, 1.0);
}`
const uvFrag = `precision highp float;
varying vec2 texcoords2;
void main() {
gl_FragColor = vec4(texcoords2.st, 0.0, 1.0);
}`
let uvShader;
let fbo;
function setup() {
createCanvas(400, 400, WEBGL);
fbo = createFramebuffer();
textureMode(NORMAL);
noStroke();
uvShader = createShader(uvVert, uvFrag);
}
function draw() {
background(33);
orbitControl();
fbo.begin();
shader(uvShader);
uvShader.setUniform('u_resolution', resolution());
uvShader.setUniform('u_zoom', int(map(mouseX, 0, width, 1, 30)));
quad(-1, -1, 1, -1, 1, 1, -1, 1);
fbo.end();
resetShader();
texture(fbo.color);
cylinder(100, 200);
}
Temporary Workaround:
Implement an extra texShader
for applying the fbo.color
texture:
const uvVert = `precision highp float;
attribute vec3 aPosition;
attribute vec2 aTexCoord;
varying vec2 texcoords2;
void main() {
texcoords2 = aTexCoord;
gl_Position = vec4(aPosition, 1.0);
}`
const uvFrag = `precision highp float;
varying vec2 texcoords2;
void main() {
gl_FragColor = vec4(texcoords2.st, 0.0, 1.0);
}`
const texVert = `precision highp float;
attribute vec3 aPosition;
attribute vec2 aTexCoord;
uniform mat4 uModelViewProjectionMatrix;
varying vec2 texcoords2;
void main() {
texcoords2 = aTexCoord;
gl_Position = uModelViewProjectionMatrix * vec4(aPosition, 1.0);
}
`
const texFrag = `precision highp float;
uniform sampler2D tex;
varying vec2 texcoords2;
void main() {
gl_FragColor = texture2D(tex, texcoords2);
}`
let uvShader, texShader;
let fbo;
function setup() {
createCanvas(400, 400, WEBGL);
fbo = createFramebuffer();
textureMode(NORMAL);
noStroke();
uvShader = createShader(uvVert, uvFrag);
texShader = createShader(texVert, texFrag);
}
function draw() {
background(33);
orbitControl();
fbo.begin();
shader(uvShader);
uvShader.setUniform('u_resolution', resolution());
uvShader.setUniform('u_zoom', int(map(mouseX, 0, width, 1, 30)));
quad(-1, -1, 1, -1, 1, 1, -1, 1);
fbo.end();
shader(texShader);
texShader.setUniform('tex', fbo.color);
cylinder(100, 200);
}
This workaround separates the texture-writing and texture-reading operations by using different shaders, avoiding the WebGL feedback loop warning. It'd be nice to be able to just call texture
.
davepagurek commented
Another workaround seems to be to put your texture within push/pop instead of using resetShader:
function draw() {
background(33);
orbitControl();
fbo.begin();
shader(uvShader);
uvShader.setUniform('u_resolution', [width, height]);
uvShader.setUniform('u_zoom', int(map(mouseX, 0, width, 1, 30)));
quad(-1, -1, 1, -1, 1, 1, -1, 1);
fbo.end();
push()
texture(fbo.color);
cylinder(100, 200);
pop()
}
nakednous commented
Yep push/pop also did the trick in a much simpler way, thanks.