Shadowmapping on iphone 3GS ?

Guys,

Anybody successfully used a FBO with a depth texture on iPhone ?

What i am trying is not working (GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT):


GLenum status; 
      
     glGenFramebuffers(1, &shadowFBOId); 
     glBindFramebuffer(GL_FRAMEBUFFER,shadowFBOId); 
      

      
     glGenTextures(1, &colorTextureId); 
     glBindTexture(GL_TEXTURE_2D, colorTextureId); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderWidth, renderHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, colorTextureId, 0); 
      
      

     glGenTextures(1, &shadowMapTextureId); 
     glBindTexture(GL_TEXTURE_2D, shadowMapTextureId); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, renderWidth, renderHeight, 0, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, NULL); 
     glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,shadowMapTextureId,0 ); 

      
 
     status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 

I’ve tried to use a Renderbuffer for the depth buffer and it is working fine (but I can’t use a renderbuffer in my shader to perform shadowmapping.

I’ve tried to remove the depth buffer attachement and again it is working fine.

I suspect the issue is in the way I set the glTexImage2D’s depth attribute.

Any clue ?

Ok, I got it working…but I can’t remove the color attachment:

FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT (0x8cdb).

openGL ES 2.0 doesn’t have a glDrawBuffer(GL_NONE)…I guess I’m going to have to dig in FBO specs…



	GLenum status;
	
	glGenFramebuffers(1, &shadowFBOId);
	glBindFramebuffer(GL_FRAMEBUFFER,shadowFBOId);

	glGenTextures(1, &shadowMapTextureId);
	glBindTexture(GL_TEXTURE_2D, shadowMapTextureId);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, renderWidth, renderHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
	glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,shadowMapTextureId,0 );
	
	
	
	status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	
	switch (status) {
		case GL_FRAMEBUFFER_COMPLETE:						printf("GL_FRAMEBUFFER_COMPLETE
");break;
		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:			printf("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
");break;
		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:	printf("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
");break;
		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:			printf("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
");break;			
		case GL_FRAMEBUFFER_UNSUPPORTED:					printf("GL_FRAMEBUFFER_UNSUPPORTED
");break;	
		default:											printf("Unknown issue (%x).
",status);break;	
	}	



There is a nice article on this in Addison Wesley’s OpenGL ES book.

Also it’s been discussed a few times in the Apple Developer Forums.

I have the book and the sample code doesn’t work ( gets a GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT).

I already searched Apple Developer Forums but I could not find anything relevant to my issue.

Spent the last 5 hours trying to make this work:

The following code passes glCheckFramebufferStatus successfully. The color texture is rendered to.

But as soon as I uncomment the last line to attach the depth buffer to the FBO, the color texture is not populated anymore.

glCheckFramebufferStatus still returns with GL_FRAMEBUFFER_COMPLETE.


	GLenum status;
	
	glGenFramebuffers(1, &shadowFBOId);
	glBindFramebuffer(GL_FRAMEBUFFER,shadowFBOId);
	
	glGenTextures(1, &colorTextureId);
	glBindTexture(GL_TEXTURE_2D, colorTextureId);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderWidth, renderHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, colorTextureId,0);
	 
	
	glGenTextures(1, &shadowMapTextureId);
	glBindTexture(GL_TEXTURE_2D, shadowMapTextureId);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, renderWidth, renderHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
	
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	//glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,shadowMapTextureId,0 );

	
	printf("colorTextureId =%u , shadowMapTextureId=%u 
",colorTextureId,shadowMapTextureId);
	
	status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	
	switch (status) {
		case GL_FRAMEBUFFER_COMPLETE:						printf("GL_FRAMEBUFFER_COMPLETE
");break;
		case 0x8CDB:										printf("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT
");break;
		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:			printf("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
");break;
		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:	printf("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
");break;
		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:			printf("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
");break;			
		case GL_FRAMEBUFFER_UNSUPPORTED:					printf("GL_FRAMEBUFFER_UNSUPPORTED
");break;	
		default:											printf("Unknown issue (%x).
",status);break;	
	}	


Interestingly, removing the:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

On the color attachment keeps glCheckFramebufferStatus happy but both attachements are not rendered to.

Shotgun anyone ?

GL_DEPTH_COMPONENT isn’t a valid format for glTexImage unless OES_depth_texture is exported.

ES doesn’t support glDrawBuffer, so there is no way to do depth-only rendering. This concept is somewhat alien to TBDRs which try to avoid allocating a depth buffer in the first place.

All of that said, it is possible to do projective shadowmapping on any of the iPhone devices, in either ES1.1 or ES2.0. The primary limitation is that you have to work with an 8 bit texture.

For depth-only rendering in ES, simply attach a depth texture and don’t use a color attachment (which of course requires support for OES_depth_texture). Any practical TBDR can write depth to external memory.

All of that said, it is possible to do projective shadowmapping on any of the iPhone devices, in either ES1.1 or ES2.0. The primary limitation is that you have to work with an 8 bit texture.

It might be worth considering object ID based approaches, or even hybrid ID/depth ones. See Tom Forsyth’s “Yet More Shadowbuffers” presentation.

Yea, I finally found out about OES_depth_texture not being supported.

As you suggested, I think I’m going to fake a DEPTH_TEXTURE by putting the z value in one of the RGB byte.

If I don’t get enough precision I will have to pack the float in a 4 RGBA. I’m going to research it but do you guys have a “best way” to do it ?

( This one: http://www.gamedev.net/community/forums/topic.asp?topic_id=442138 looks pretty neat)