I can't find the glTexImage3D()
function from OpenGL in OpenGL ES 2.0. So how can I use a 3-D texture, eg: a .tga file?
Does someone know how to use a 3-D texture in OpenGL ES 2.0?
I can't find the glTexImage3D()
function from OpenGL in OpenGL ES 2.0. So how can I use a 3-D texture, eg: a .tga file?
Does someone know how to use a 3-D texture in OpenGL ES 2.0?
OpenGL ES 1.x and 2.x doesn't mandate support for 3d textures — see e.g. the canonical man page for glBindTexture
, which lists only GL_TEXTURE_2D
and GL_TEXTURE_CUBE_MAP
as targets — and the iOS hardware doesn't provide any suitable extension.
The best solution I've been able to come up with is packing a 3d texture as though it were a 2d texture, so you've got say a 128x128x128 3d texture and you lay it out as 128 separate 128x128 images in an 16x8 grid on a single 2d texture. So the 2d texture is 2048x1024 pixels, getting close to the hardware limit on the iPhone 4 and iPad 2 generation of devices and the ES 2.0 compatible iOS devices that preceded them.
You then feed a 3d texture coordinate to your fragment shader exactly as if there were a way to index 3d textures natively, but do a quick bit of maths to collapse it to 2d.
So, in the 128x128x128 example, you'd do something like (coded here, as I talk, untested, ):
texPos.x = sourceVarying.x / 16.0; // because we've packed 16 source images across,
texPos.y = sourceVarying.y / 8.0; // and 8 images down
// we'll multiply z by 16 since then, logically, the integer part is
// how many tiles across to index, and the decimal part is now many
// tiles down to index
texPos.z *= 16.0;
// figure out how many tiles across to index, with each tile being
// 1.0 / 16.0 in size
texPos.x += floor(texPos.z) / 16.0;
// remove the integer part of z, then multiply by 8 to do much what
// we just did to y
texPos.z = fract(texPos.z) * 8.0;
texPos.y += floor(texPos.z) / 8.0;
// now load the appropriate sample from texPos.xy
That's probably not the most efficient way to achieve that, it's written for (relative) clarity. You're also looking at the significant performance disadvantage of every texture read being dependent (ie, the GPU can't predict the accesses outside of the fragment shader, causing significant pipeline difficulties). But that's to be weighed against whatever costs you would have to expend to use something other than 3d texture maps.
Notice also that you're doing one access that's tied to a particular z slice. So you're limited to GL_NEAREST
-type sampling in at least one dimension unless you want to do two samples and mix the result yourself at even greater cost. I've also done nothing about clamping, which you'll quite possibly want to address.
Datenwolf (+1, incidentally) is also entirely correct about mipmapping being an issue; I ended up just disabling it.
Late 2013 addendum: at the time of writing, iOS 7, the iPhone 5s, the second generation iPad Mini and the iPad Air all support ES 3.0. 3.0 introduces the GL_TEXTURE_3D
target. So you can use 3d texturing directly on those devices and, probably, all future iOS devices. And, for the record, it's seeing similar availability on Android, having been supported in all the recent Nexus devices, the HTC One, a few of the recent Samsungs and others.
I can't found there is glTexImage3D function in OpenGL ES 2
Because 3D textures are not supported by OpenGL-ES. Think about it: A 3D texture requires a lot more memory than a 2D one. And memory is a very scarce resource on embedded/mobile devices, which is what ES is targeted for.
I think maybe someone knows the algorithm of using 3d texture?
It's not so much a algorithmic problem but one of limited resources. In theory you could use multiple texture units/samplers to upload layers there, and do interpolation in the shader. But this would lack depth mipmaping.
3d texture, eg: .tag file?
TAG file? Sorry, I'm unaware of this format. Could you give me a link to read it up? Google didn't find usefull information on it. Did you maybe mean TGA?