Dual depth peeling

Good afternoon,

have you tried dual depth peeling with lights? I have version of Bavoil source code in opengl 3.3 and I would like to know, where should I light object. When I had lighted each peeled pass I got very bright result. Should I light it in final shader?

Thank you.

Computing lighting after depth peeling (eg deferred shading) would mean storing and peeling extra data. Unless your lighting is very expensive it might be simpler to compute during depth peeling, especially if you’re keeping all layers and compositing later.

My assumption is the bright result you’re getting might be to do with the way you’re blending each layer. Double check the alpha you write during depth peeling is correct and that your compositing uses the right method. Eg:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
for the back layers and, purely quoting from the paper:
glBlendEquation(GL_FUNC_ADD);
glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA)
for the front layers.

Since you’re using opengl 3.3, have you had a look at some of the single-pass order-independent transparency methods? (Eg. with linked lists or packing using prefix sum/scan).

I have peeling algorithm like this.

glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);

	glBindFramebuffer(GL_FRAMEBUFFER, dualDepthFBOID);

	// Render targets 1 and 2 store the front and back colors
	// Clear to 0.0 and use MAX blending to filter written color
	// At most one front color and one back color can be written every pass
	glDrawBuffers(2, &drawBuffers[1]);
	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT);

	GL_CHECK_ERRORS

	// Render target 0 stores (-minDepth, maxDepth, alphaMultiplier)
	glDrawBuffer(drawBuffers[0]);	
	glClearColor(-MAX_DEPTH, -MAX_DEPTH, 0, 0);	
	glClear(GL_COLOR_BUFFER_BIT);
	glBlendEquation(GL_MAX);
	DrawScene(MVP, initShader);  

	// 2. Depth peeling + blending pass
	glDrawBuffer(drawBuffers[6]);
	glClearColor(bg.x, bg.y, bg.z, bg.w);
	glClear(GL_COLOR_BUFFER_BIT);

	int numLayers = (NUM_PASSES - 1) * 2;
	int currId = 0;
	for (int layer = 1; bUseOQ || layer < numLayers; layer++) {
		currId = layer % 2;
		int prevId = 1 - currId;
		int bufId = currId * 3;

		glDrawBuffers(2, &drawBuffers[bufId+1]);
		glClearColor(0, 0, 0, 0);
		glClear(GL_COLOR_BUFFER_BIT);

		glDrawBuffer(drawBuffers[bufId+0]);
		glClearColor(-MAX_DEPTH, -MAX_DEPTH, 0, 0);
		glClear(GL_COLOR_BUFFER_BIT);

		// Render target 0: RG32F MAX blending
		// Render target 1: RGBA MAX blending
		// Render target 2: RGBA MAX blending
		glDrawBuffers(3, &drawBuffers[bufId+0]);
		glBlendEquation(GL_MAX);
		glBlendFuncSeparate(GL_DST_ALPHA,GL_ONE,GL_ZERO,GL_ONE_MINUS_SRC_ALPHA);
		 
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_RECTANGLE, depthTexID[prevId]);

		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_RECTANGLE, texID[prevId]);
		DrawScene(MVP, dualPeelShader, true,true);
		
		// Full screen pass to alpha-blend the back color
		glDrawBuffer(drawBuffers[6]);

		glBlendEquation(GL_FUNC_ADD);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

		if (bUseOQ) {
			glBeginQuery(GL_SAMPLES_PASSED_ARB, queryId);
		}

		GL_CHECK_ERRORS

		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_RECTANGLE, backTexID[currId]);
		blendShader.Use();		 
			 DrawFullScreenQuad();
		blendShader.UnUse();

		if (bUseOQ) {
			glEndQuery(GL_SAMPLES_PASSED);
			GLuint sample_count;
			glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, &sample_count);
			if (sample_count == 0) {
				break;
			}
		} 
		GL_CHECK_ERRORS 
	} 

	GL_CHECK_ERRORS

	glDisable(GL_BLEND);

	// 3. Final render pass
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glDrawBuffer(GL_BACK_LEFT);
	
	glBindTexture(GL_TEXTURE_RECTANGLE, colorBlenderTexID);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_RECTANGLE, depthTexID[currId]);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_RECTANGLE, texID[currId]);
	glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_RECTANGLE, colorBlenderTexID);
	finalShader.Use(); 
		DrawFullScreenQuad();
	finalShader.UnUse();

So I tried glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA) and that threw same result. I think, that this can add so much vertex colors, that it can result to extremly brighted color. Maybe I try change GL_ADD with GL_MAX

Without going into the code in detail, do you have both a front and back temporary buffer for compositing layers in each direction? Eg after peeling a front and back layer in a single pass, each is blended to a separate temporary buffer before finally blending the front temporary with the back (getting the alpha of the front temporary here is important too). At least this was my understanding of dual depth peeling.

Also, if you have many layers with a small amount of alpha you might need floating point temporaries. Although this would make the image darker, not brighter.

Finally, all I can suggest is add a nice way to debug your intermediate data and create a very simple scene. Something so you can calculate the values of the colours yourself. Starting with opaque geometry really helps here.