order independent transparency via casual effects

Started by cathi, July 03, 2016, 15:07:07

Previous topic - Next topic

cathi

hi everyone

i've been trying to implement the order independent transparency approach outlined here: http://casual-effects.blogspot.com/2015/03/implemented-weighted-blended-order.html

but i can't seem to get it working!

i've looked at the c++ code by the original author: https://sourceforge.net/p/g3d/code/5769/tree/G3D10/GLG3D.lib/source/DefaultRenderer.cpp and https://sourceforge.net/p/g3d/code/5769/tree/G3D10/data-files/shader/DefaultRenderer/DefaultRenderer_compositeWeightedBlendedOIT.pix and the python port by a separate dev: http://dept.cs.williams.edu/~morgan/code/python/python-oit.zip

this is what my code looks like:

intialisation:

GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glEnable(GL32.GL_DEPTH_CLAMP);


texture setup for accumulation and revealage textures:

       
fboId = GL30.glGenFramebuffers();
		// fboTexId = GL11.glGenTextures();
		depthBufferId = GL30.glGenRenderbuffers();
		accumulationTexId = GL11.glGenTextures();
		revealageTexId = GL11.glGenTextures();

		
	GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fboId);
		
	GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBufferId);
	GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL30.GL_DEPTH_COMPONENT32F, WIDTH, HEIGHT);
	GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER, depthBufferId);
	GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, 0);

	GL11.glBindTexture(GL11.GL_TEXTURE_2D, accumulationTexId);
	GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, WIDTH, HEIGHT, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, BufferUtil.arrayAsByteBuffer(new byte[WIDTH * HEIGHT * 4]));
	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
	GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
		
	GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, // 1. fbo target:
			GL30.GL_COLOR_ATTACHMENT0, // 2. attachment point
			GL11.GL_TEXTURE_2D, // 3. tex target: GL_TEXTURE_2D
			accumulationTexId, // 4. tex ID
			0);
	
	GL11.glBindTexture(GL11.GL_TEXTURE_2D, revealageTexId);
	GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, WIDTH, HEIGHT, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, BufferUtil.arrayAsByteBuffer(new byte[WIDTH * HEIGHT * 4]));
	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
	GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
	GL30.glClearBuffer(GL11.GL_COLOR, 1, BufferUtil.arrayAsFloatBuffer(new float[]{1,0,0,1}));

	GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, // 1. fbo target:
			GL30.GL_COLOR_ATTACHMENT1, // 2. attachment point
			GL11.GL_TEXTURE_2D, // 3. tex target: GL_TEXTURE_2D
			revealageTexId, // 4. tex ID
			0);	
		
	GL20.glDrawBuffers(BufferUtil.arrayAsIntBuffer(new int[]{GL30.GL_COLOR_ATTACHMENT0, GL30.GL_COLOR_ATTACHMENT1}));
		
	int status = GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER) ;
	if (status != GL30.GL_FRAMEBUFFER_COMPLETE) {
		System.out.println(status);
	System.exit(0);
}


GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);


render cycle:

GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
	   
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
	    
GL11.glDepthMask(true); // depth buffer is now written to, i.e. prevents further away fragments from being written to the buffer
GL11.glDisable(GL11.GL_BLEND);

renderOpaqueMeshes();
		    
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fboId);
	    	    
GL11.glDrawBuffer(GL30.GL_COLOR_ATTACHMENT0);
GL11.glClearColor(0,0,0,0);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
	    
GL11.glDrawBuffer(GL30.GL_COLOR_ATTACHMENT1);
GL11.glClearColor(1,0,0,0);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
	    
GL20.glDrawBuffers(BufferUtil.arrayAsIntBuffer(new int[]{GL30.GL_COLOR_ATTACHMENT0, GL30.GL_COLOR_ATTACHMENT1}));	    
	    
GL11.glDepthMask(false); // depth buffer is now only read from, i.e. does not prevent fragments further away from being drawn
GL11.glEnable(GL11.GL_BLEND);
GL14.glBlendEquation(GL14.GL_FUNC_ADD);
	    
GL14.glBlendFuncSeparate(GL11.GL_ONE,  GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE_MINUS_SRC_COLOR);	  
	    
renderTranslucentMeshes();
	    
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);	    
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

renderComposite();


my renderComposite() function looks like:

GL20.glUseProgram(Shader.compositeShaderProgram);

// Bind to the VAO that has all the information about the quad vertices
GL30.glBindVertexArray(compositeRenderData.vaoId);
GL20.glEnableVertexAttribArray(0);        
        
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, accumulationTexId);
		
GL13.glActiveTexture(GL13.GL_TEXTURE1);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, revealageTexId);
      
// Draw the vertices
		
// bind our buffer
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, compositeRenderData.vboId);		
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, compositeRenderData.verticesToRender);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
        
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
		
GL13.glActiveTexture(GL13.GL_TEXTURE1);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
         
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
		
GL20.glUseProgram(0);


transulcent fragment shader:

#version 330
 
// vertex data is passed here

layout (location = 0) out vec4 col0rgba;
layout (location = 1) out vec4 col1r;

void main(void) {

  vec3 directionToEye = normalize(eyePos - pass_WorldPos);
  vec4 color = vec4(1,1,1,1);
  vec4 totalLight = vec4(ambientColor,1);
  float c = NUM_TEXTURES*pass_TexOffset+0;
  vec4 textureColor = texture(diffuseTexture, vec3(pass_TextureCoord, c));
  
  
  if (textureColor != vec4(0,0,0,0)){
    color *= textureColor;
  }
  
  if (pass_Shadeless != 1.0f){
	 
	  vec3 normal = pass_Normal;
	
	  if (renderNormal == 1.0){
	    float d = NUM_TEXTURES*pass_TexOffset+1;
	    normal = normalize(pass_TbnMatrix * (255.0/128.0 * texture(diffuseTexture, vec3(pass_TextureCoord, d)).xyz - 1));
	  }
	
	  for(int i = 0; i < MAX_DIRECTIONAL_LIGHTS; i++)
	    if(directionalLights[i].base.intensity > 0)
	      totalLight += calcDirectionalLight(directionalLights[i], normal);
	
	  for(int i = 0; i < MAX_POINT_LIGHTS; i++)
	    if(pointLights[i].base.intensity > 0)
	      totalLight += calcPointLight(pointLights[i], normal);
	
	  for(int i = 0; i < MAX_SPOT_LIGHTS; i++)
	    if(spotLights[i].pointLight.base.intensity > 0)
	      totalLight += calcSpotLight(spotLights[i], normal);
  }
  
  vec4 fCol = (color * totalLight);
  
  float a = min(1.0, fCol.a) * 8.0 + 0.01;
  float b = -pass_vDepth * 0.95 + 1.0;
  
  float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2);
  
  col0rgba.rgb = fCol.rgb * a;
  col0rgba.a = a;
  col0rgba = col0rgba * w;
  
  col1r = vec4(fCol.a, 0, 0, 0);
  
}


and my composite shader looks like:

#version 330

uniform sampler2D accumulation;
uniform sampler2D revealage;

in vec2 pass_TextureCoord;

out vec4 out_Color;

float maxComponent (vec4 v) {
  return max (max ( max(v.x, v.y), v.z), v.w);
}

void main(void) {

  float  revealage = texture(revealage, pass_TextureCoord).r;
  
  if (revealage == 1.0) {
    //Save the blending and color texture fetch cost
    discard; 
  }
  
  vec4  accum = texture(accumulation, pass_TextureCoord);
  
  if (isinf(maxComponent(abs(accum)))) {
      accum.rgb = vec3(accum.a);
  }
  
   vec3 averageColor = accum.rgb / max(accum.a, 0.00001);
  
  out_Color = vec4(averageColor, 1.0 - revealage);
  
}


however! when i run my application, i get this:



i.e. my whole screen is filled with red, but if i move forward a little, the objects in my scene appear, before being occluded by the red render

i guess first off, are my textures configured per the specification on the blog post?

and am i writing to the accum/revealage textures correctly from my translucent fragment shader?

and is my composite shader correct?

i'm not sure what could be causing this red plane to overwrite my screen render

any help anyone can offer is greatly appreciated!

thanks :)