PDA

View Full Version : Shadowmapping on iphone 3GS ?



nicolasbol
09-29-2009, 06:00 PM
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_ATT ACHMENT,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 ?

nicolasbol
09-29-2009, 06:11 PM
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_ATT ACHMENT,GL_TEXTURE_2D,shadowMapTextureId,0 );



status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

switch (status) {
case GL_FRAMEBUFFER_COMPLETE: printf("GL_FRAMEBUFFER_COMPLETE\n");break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: printf("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n");break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: printf("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n");break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: printf("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS\n");break;
case GL_FRAMEBUFFER_UNSUPPORTED: printf("GL_FRAMEBUFFER_UNSUPPORTED\n");break;
default: printf("Unknown issue (%x).\n",status);break;
}

scratt
09-29-2009, 08:14 PM
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.

nicolasbol
09-29-2009, 08:42 PM
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.

nicolasbol
09-29-2009, 11:01 PM
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_ATT ACHMENT,GL_TEXTURE_2D,shadowMapTextureId,0 );


printf("colorTextureId =%u , shadowMapTextureId=%u \n",colorTextureId,shadowMapTextureId);

status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

switch (status) {
case GL_FRAMEBUFFER_COMPLETE: printf("GL_FRAMEBUFFER_COMPLETE\n");break;
case 0x8CDB: printf("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n");break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: printf("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n");break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: printf("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n");break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: printf("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS\n");break;
case GL_FRAMEBUFFER_UNSUPPORTED: printf("GL_FRAMEBUFFER_UNSUPPORTED\n");break;
default: printf("Unknown issue (%x).\n",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 ?

arekkusu
09-30-2009, 06:28 AM
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.

Xmas
09-30-2009, 07:10 AM
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.
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" (http://home.comcast.net/~tom_forsyth/papers/papers.html) presentation.

nicolasbol
09-30-2009, 08:16 AM
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)