mache Posted May 4, 2016 Share Posted May 4, 2016 Hello guys, I would like to make a debugger such one of these: -http://www.paulallenrenton.com/individual-projects/webgl-deferred-renderer -http://codeflow.org/entries/2012/aug/25/webgl-deferred-irradiance-volumes/#debugging I am trying to use multiple rendering target with this webgl extension => (https://www.khronos.org/registry/webgl/extensions/WEBGL_draw_buffers/), so when I am rendering my scene I would like in my fragment shader to write something like this: #extension GL_EXT_draw_buffers : require precision highp float; uniform sampler2D positionSampler; uniform sampler2D normalSampler; uniform sampler2D depthSampler; uniform sampler2D stuffSampler; varying vec2 vUV2; void main(void) { gl_FragData[0] = texture2D(positionSampler, vUV2); gl_FragData[1] = texture2D(normalSampler, vUV2); gl_FragData[2] = texture2D(depthSampler, vUV2); gl_FragData[3] = texture2D(stuffSampler, vUV2); } with each gl_FragData writing in a webgl texture associated. I didn't find a lots resources about it on the internet... I am working with babylon.js, any example or help would be great. Thanks ! Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 4, 2016 Share Posted May 4, 2016 Hello you need to change babylon.js a bit for now and add this kind of code: var fb = gl.createFramebuffer(); gl.bindFramebuffer(gl.FRAMEBUFFER, fb); gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_2D, tx[0], 0); gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, tx[1], 0); gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT2_WEBGL, gl.TEXTURE_2D, tx[2], 0); gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT3_WEBGL, gl.TEXTURE_2D, tx[3], 0); Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 4, 2016 Share Posted May 4, 2016 Great post to read: https://hacks.mozilla.org/2014/01/webgl-deferred-shading/ Quote Link to comment Share on other sites More sharing options...
mache Posted May 4, 2016 Author Share Posted May 4, 2016 Hello, Thanks for your answer, I have already test something like this but I had no result... I will take a look at this post. Quote Link to comment Share on other sites More sharing options...
mache Posted May 9, 2016 Author Share Posted May 9, 2016 Hello, I have read the article and since I've tried something similar I am stuck right now. Here are samples of my code: vertex and fragment shader /*************************** FRAGMENT ***************************/ #extension GL_EXT_draw_buffers : require precision highp float; uniform sampler2D positionSampler; uniform sampler2D normalSampler; varying vec2 vUV2; void main(void) { vec4 renderTarget1 = texture2D(normalSampler, vUV2); vec4 renderTarget2 = texture2D(positionSampler, vUV2); gl_FragData[0] = vec4(1.0,0.0,0.0,1.0); gl_FragData[1] = vec4(0.5,0.5,0.5,1.0); gl_FragData[2] = vec4(0.0,1.0,0.0,1.0); gl_FragData[3] = vec4(0.0,0.0,1.0,1.0); } /*************************** VERTEX ***************************/ precision highp float; // Attributes attribute vec3 position; attribute vec2 uv2; // Uniforms uniform mat4 worldViewProjection; // Varying varying vec2 vUV2; void main(void) { gl_Position = worldViewProjection * vec4(position, 1.0); vUV2 = uv2; } and the javascript var interval; //material init var mrtMaterial = new BABYLON.ShaderMaterial("mrt", _scene, "./src/Components/Demo/Shaders/mrt", { attributes: ["position", "uv2"], uniforms: ["worldViewProjection"] }); mrtMaterial.setTexture("normalSampler", normalTexture); mrtMaterial.setTexture("positionSampler", positionTexture); mrtMaterial.backFaceCulling = false; //get the size of canvas var canvas = document.getElementsByTagName("canvas")[0]; var size = { width: canvas.width / 3, // split 3 times on the width hard coded height: canvas.height / 2 // split 2 times on the height hard coded }; //return a new webgl texture sized to canvas var getWebGLTexture = function(gl) { var webglTexture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, webglTexture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 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, gl.RGBA, size.width, size.height, 0, gl.RGBA, gl.FLOAT, null); gl.bindTexture(gl.TEXTURE_2D, null); return webglTexture; }; //meshes list var renderList = MESHES.slice(0); //render target associate to the material var mrtTarget = RenderTargetManager.CreateForEffectOnce("mrtTarget", mrtMaterial, _scene, size, renderList, false); //when material + textures used + render target are ready function onReady() { if (!mrtMaterial.isReady() || !positionTexture.isReady() || !normalTexture.isReady() || !mrtTarget.isReady()) return; clearInterval(interval); var gl = _scene.getEngine()._gl; var targets = []; var nbTargets = 4;//yield 5 screen, so split 3 times on width and 2 on the height //activate extension var drawBuffersExtension = gl.getExtension('WEBGL_draw_buffers') || gl.getExtension("GL_EXT_draw_buffers") || gl.getExtension("EXT_draw_buffers"); if (!drawBuffersExtension) { throw new Error("draw buffer extension not supported"); } //return an attachment color with a given i var getFlag = function(i) { var flag; switch (i) { case 0: flag = drawBuffersExtension.COLOR_ATTACHMENT0_WEBGL break; case 1: flag = drawBuffersExtension.COLOR_ATTACHMENT1_WEBGL break; case 2: flag = drawBuffersExtension.COLOR_ATTACHMENT2_WEBGL break; case 3: flag = drawBuffersExtension.COLOR_ATTACHMENT3_WEBGL break; case 4: flag = drawBuffersExtension.COLOR_ATTACHMENT4_WEBGL break; case 5: flag = drawBuffersExtension.COLOR_ATTACHMENT5_WEBGL break; default: throw new Error("flag limit"); break; } return flag; } //get the framebuffer of the render target and bind it gl.bindFramebuffer(gl.FRAMEBUFFER, mrtTarget._texture._framebuffer ); //init textures for (let i = 0; i < nbTargets; i++) { if (i === 0) { //insert a canvas into html and associate the webgl texture of the render target to it var indexDbg = debugger3D.insertWebGLTexture(mrtTarget._texture, _scene, size, (i + 1).toString()); var target = { texture: mrtTarget._texture, indexDbg: indexDbg, flag: getFlag(i) } } else { //insert a canvas into html and associate a webgl texture to it var texture = getWebGLTexture(gl); var indexDbg = debugger3D.insertWebGLTexture(texture, _scene, size, (i + 1).toString()); var target = { texture: texture, indexDbg: indexDbg, flag: getFlag(i) } } //bind webgl texture to different attachement gl.framebufferTexture2D(gl.FRAMEBUFFER, target.flag, gl.TEXTURE_2D, target.texture, 0); targets.push(target); } //return true console.log("FrameBuffer status after initialization: "); console.log(gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_UNSUPPORTED); var buffers = []; //map color attachement to draw buffer for (let i = 0; i < targets.length; i++) { buffers.push(targets[i].flag); } drawBuffersExtension.drawBuffersWEBGL(buffers); //execute the rendering pass mrtTarget.render(); //unbind gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.bindTexture(gl.TEXTURE_2D, null); //for each canvas inserted read the webgl texture pixel by pixel and draw it for (let i = targets.length - 1; i >= 0; i--) { debugger3D.draw(targets[i].indexDbg); } // when webgl textures were empty I had some warning that I don't have anymore } interval = setInterval(onReady, 250); I joined an image of what displayed on the screen. The gl_FragData[0] associated to the render target webgl texture is drawn ( y are inversed which is normal), but none of the others are rendering... What I am missing ? Thanks for any help. Quote Link to comment Share on other sites More sharing options...
mache Posted May 9, 2016 Author Share Posted May 9, 2016 I tried to make a playground => http://www.babylonjs-playground.com/#1PAREU#9 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 9, 2016 Share Posted May 9, 2016 where do you bind all targets? Quote Link to comment Share on other sites More sharing options...
mache Posted May 10, 2016 Author Share Posted May 10, 2016 This line bind the webgl texture to a color attachment of the framebuffer => gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, texture._texture, 0); (line 96 of the playground) Then color attachment are mapped to draw buffer slots here => ext.drawBuffersWEBGL([ext.COLOR_ATTACHMENT0_WEBGL,ext.COLOR_ATTACHMENT1_WEBGL]); (line 103) I guess this is how targets are binded. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 10, 2016 Share Posted May 10, 2016 yes but to make it works you need to bind 4 textures. Quote Link to comment Share on other sites More sharing options...
mache Posted May 11, 2016 Author Share Posted May 11, 2016 I update the playground it looks like this now : gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT0_WEBGL, gl.TEXTURE_2D, textures[0]._texture, 0); gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT1_WEBGL, gl.TEXTURE_2D, textures[1]._texture, 0); gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT2_WEBGL, gl.TEXTURE_2D, textures[2]._texture, 0); gl.framebufferTexture2D(gl.FRAMEBUFFER, ext.COLOR_ATTACHMENT3_WEBGL, gl.TEXTURE_2D, textures[3]._texture, 0); then : ext.drawBuffersWEBGL([ext.COLOR_ATTACHMENT0_WEBGL, ext.COLOR_ATTACHMENT1_WEBGL, ext.COLOR_ATTACHMENT2_WEBGL, ext.COLOR_ATTACHMENT3_WEBGL]); Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 11, 2016 Share Posted May 11, 2016 And is it better? Quote Link to comment Share on other sites More sharing options...
mache Posted May 11, 2016 Author Share Posted May 11, 2016 No it's the same instead of having 1 empty texture I have 4, in the post where I put some code I had already 4 textures but no result... Quote Link to comment Share on other sites More sharing options...
mache Posted May 12, 2016 Author Share Posted May 12, 2016 I installed this debugger webgl (https://www.khronos.org/webgl/wiki/Debugging) to console.log all webgl call. I join a txt file with the output. The first time I map a framebuffer attachment with a texture I got : gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, [object WebGLTexture], 0) then for the others I got : gl.framebufferTexture2D(gl.FRAMEBUFFER, /*UNKNOWN WebGL ENUM*/ 0x8ce1, gl.TEXTURE_2D, [object WebGLTexture], 0) the hexadecimal value is correct according to the documentation but do you think is that normal ? glDebugOutput Quote Link to comment Share on other sites More sharing options...
mache Posted May 17, 2016 Author Share Posted May 17, 2016 Hello, So I solved my problem, actually my use of the draw buffer extension was right but I was checking the framebuffer bounded and not webgl textures. Is there a way to read in a webgl texture with a function like gl.readPixel (to read pixel by pixel in a framebuffer) so I could draw in a separate canvas multiple result of my rendering pass. I can't use a solution like describe here (http://stackoverflow.com/questions/13626606/read-pixels-from-a-webgl-texture) because I've already attach my texture to a framebuffer, but I don't know how to access color buffers of this latter. Thanks. dbawel 1 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 17, 2016 Share Posted May 17, 2016 This is a great news! Quote Link to comment Share on other sites More sharing options...
mache Posted May 18, 2016 Author Share Posted May 18, 2016 Finally I got it I found my answer here => http://stackoverflow.com/questions/34154300/readpixels-on-multiple-draw-buffers-in-webgl, I added more framebuffers and bound them to my color buffers in order to access them with readPixels function. Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 18, 2016 Share Posted May 18, 2016 would love to see it Quote Link to comment Share on other sites More sharing options...
mache Posted May 19, 2016 Author Share Posted May 19, 2016 sure here it is ! fragment looks like this => #extension GL_EXT_draw_buffers : require precision highp float; uniform sampler2D positionSampler; uniform sampler2D normalSampler; varying vec2 vUV2; void main(void) { vec4 renderTarget1 = texture2D(normalSampler, vUV2); vec4 renderTarget2 = texture2D(positionSampler, vUV2); gl_FragData[0] = vec4(0.0,1.0,0.0,1.0); gl_FragData[1] = renderTarget1; gl_FragData[2] = renderTarget2; gl_FragData[3] = vec4(0.0,0.0,1.0,1.0); } Debugger mrt.webm NasimiAsl 1 Quote Link to comment Share on other sites More sharing options...
GameMonetize Posted May 19, 2016 Share Posted May 19, 2016 Excellent! NasimiAsl 1 Quote Link to comment Share on other sites More sharing options...
Paul Renton Posted January 11, 2022 Share Posted January 11, 2022 Wish I saw this earlier. I can share the entire code on Github. Just let me know. I could do an overview on Render Targets and their uses, both engine and gameplay. I used them for the mini-map (Automap) on Doom Eternal. [email protected] Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.