Sign in to follow this  
Geometrian

OpenGL 3D Textures

Recommended Posts

Geometrian    1810
Hi, I recently got 3D textures working in my OpenGL application. It would be nice to have some 3D textures to work with, though. Presently, I'm just taking a 2D image and using it (depth=1), but I know greater things are possible. On a slight tangent, how are 3D textures stored? I had the idea to use a 2D image. Suppose you have a 512x512 image, that can hold the data for a 64x64x64 texture. Is this the way 3D textures are typically stored? I'm hoping for a metallic 3D texture, as that fits nicely into my new game, but really any sort of 3D texture would be good right now. Any decent free resources? I couldn't find any... Thanks, Ian

Share this post


Link to post
Share on other sites
rouncED    103
Yeh 3d textures are amazing, they are just a bunch of 2d textures on top of each other.

Did you know, you can actually create a high detail 3d voxel surface on top of your triangle models, and you can render any kind of advanced 3d voxel pattern.

And you can probably draw 10 flat sprites on top of each other and you could make things like grass on the surface of a landscape.

Its just a matter of making the grass model in 3dsmax, convert it to 3d textures, then displaying in game, 256 flats ontop of each other restoring the grass in 3d.

Theres almost no difference in just storing 10 normal textures as aposed to loading a single 3d texture with 10 layers... its just you get special 3d retrieves from a 3d texture, when you Tex2DLod()

Share this post


Link to post
Share on other sites
Yann L    1802
Quote:
Original post by rouncED
Yeh 3d textures are amazing, they are just a bunch of 2d textures on top of each other.

They're a bit more than that. Texture arrays are essentially just 'a bunch of 2D textures', but even they have some very significant differences.

Quote:
Original post by rouncED
Theres almost no difference in just storing 10 normal textures as aposed to loading a single 3d texture with 10 layers...

There are a lot of differences. First off, a 3D texture allows quad-linear interpolation, instead of the trilinear 2D texture interpolation. The hardware will also interpolate on the depth axis. Second, mipmap sizes are defined by a cubic function, instead of a quadratic one. Third, a 3D texture is a monolithic structure, from the point of view of the GPU. It cannot be partially swapped out of VRAM, even if you only use a small subset of it. This is very different from a set of 2D textures, which can be partially swapped. And last, most importantly, you can sample a 3D texture by using a single texture lookup with a three component vector. This is totally impossible with a bunch of 2D texture, where each texture requires a separate image unit, a separate lookup and complicated logical to actually select the right images and interpolants.

Quote:

On a slight tangent, how are 3D textures stored? I had the idea to use a 2D image. Suppose you have a 512x512 image, that can hold the data for a 64x64x64 texture. Is this the way 3D textures are typically stored?

Depends on the GPU architecture. Most GPUs don't even store 2D textures in the straightforward way, due to texture cache issues. From the host application point of view, 3D textures are stored per slice.

3D textures are very useful, but don't get too excited about using them everywhere. They take up a lot of memory. A simple RGBA 512³ texture will eat up 512 MB VRAM ! In fact, the best usage scenarios for 3D textures involve very asymmetric texture sizes, for example 512*512*4. They're used to store more information per pixel then a typical RGBA texture can provide (16 components instead of the usual 4, in this example). This can be used to store spherical harmonic coefficients in a lightmap, for example.

Share this post


Link to post
Share on other sites
PolyVox    712
Here's a rather cool paper about generating 3D (solid) textures from 2D examples:

Solid Texture Synthesis from 2D Exemplars

Unfortunatly I've asked the author for source code/executable but haven't got anywhere.

One advantage of 3D textures is that you don't need to specify UV texture coordinates for you models. Instead, you can just use the vertex positions as texture coordinates (possibly scaled, rotated, etc). This makes then useful for texturing proceduraly generated geometry, or geometry which changes dynamically.

Disadvantages include the memory required, and the fact that they are hard to generate. You could generate them procedurally, but you might also want to look at exporting them from 3D modelling packages. Such packages typically have a 3D material editor. If you rendered this material onto a bunch of adjacent slices you could take the resultig images and rebuild the 3D texture. Scripting could make this automatic...

Share this post


Link to post
Share on other sites
Krokhin    218
Quote:
Original post by Geometrian
I'm hoping for a metallic 3D texture, as that fits nicely into my new game, but really any sort of 3D texture would be good right now. Any decent free resources? I couldn't find any...

3D-textures consist from layers,but has more specific mipmaping-in their mipmaps neighbouring layers are also mixed.And the sampling time from 3D-textures takes more time than usual. One of their advantages is possibility of sampling "between" layers,but if you will try to interpolate 1st and 3rd layers for example,you can't skip 2nd. And so on.

Share this post


Link to post
Share on other sites
Geometrian    1810
I'm thinking something small (like 643) will be entirely sufficient for my purposes. That amount of data should be about as much as a single 5122 texture.

I think the point about using it for extra color channels is awesome.

Likewise, PolyVox, that link is great! Something like that is perfect--but I need something to work from; that paper is pretty impassible...

-G

Share this post


Link to post
Share on other sites
PolyVox    712
I should have pointed out that he does have some example textures for download here: http://johanneskopf.de/publications/solid/textures/index.html

However, you will need to decode the file format (doubt if it's complex). But after some examination I noticed that the textures lack high frequency detail - that is, they look blurred compared to the 2D examples. Guess the algorithm needs more work but it's still pretty impressive.

Share this post


Link to post
Share on other sites
Geometrian    1810
I thought those were 2D textures, so I missed them...

Alright, so decoding the file system. They give this spec on the matter. I'm trying to translate this to Python. Any clues--or would this be better in the Scripting Languages forum...? (I'm working with "corral.vol" which I presume is a misspelling of "coral"...)

So far, I've got:
file = open("coral.vol", "r")
header = file.read(4096)
The header data is apparently turned into a struct (class) VolumeHeader. The rest of the file is then read. Should be simple enough to convert--if I were more familiar with C languages...

-G

[Edited by - Geometrian on June 20, 2009 6:30:37 PM]

Share this post


Link to post
Share on other sites
PolyVox    712
I'm not familiar with Python, but I agree it should be simple to convert. It looks like a pretty basic format - no compression etc. But yes, a Python forum might be able to help more...

Share this post


Link to post
Share on other sites
PolyVox    712
Quote:
Original post by Geometrian
Getting back to the main topic, is there some standard for storing volumetric textures?


The most widely used format for volume data is DICOM, but this is heavily oriented towards storing medical data. It's not partcularly suitable for games.

Microsofts DDS texture format has support for volume textures, as described here. They also have some more general information here. This is probably the easiest approach.

For a more 'open source' solution, I've wondered whether the .mng file format could be used to hold volume data. It's essentially a series of .png images, designed for animation but I don't see why it couldn't be a series of slices in a volume. Read more here.

Quote:
Original post by GeometrianAs I understand it, they're mostly procedural, but not every 3D texture I've seen is that way.


The way in which textures (both 2D and 3D) are created is usually independant of the way in which they are stored. So you could create the texture procedurally, and then save it using one of the formats above.

Share this post


Link to post
Share on other sites
Geometrian    1810
DICOM sounds interesting, especially as there must be a lot of textures for it (Wikipedia, for instance, seems to make exclusive use of medical volume textures to explain the concept). However, it looks like an overkill for procedure...

DDS might work--I found this describing how to load it. Especially if other applications use DDS, it would be good to have code to use it. On the other hand, at the link at least, 3D textures don't seem to be supported...

I have used MNG with Jasc Animation Shop (Version 2.02, mind you, quite old) and I can easily see how that idea would work. I think it best if it were done automatically, however.

I think the best approach for my code for maximum compatibility is to be able to load as many types as possible--in this case, starting with .dds, .vol, and .mng in that order.

Then, someone needs to make a REALLY AWESOME 3D texture creator and create a standard...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By Zaphyk
      I am developing my engine using the OpenGL 3.3 compatibility profile. It runs as expected on my NVIDIA card and on my Intel Card however when I tried it on an AMD setup it ran 3 times worse than on the other setups. Could this be a AMD driver thing or is this probably a problem with my OGL code? Could a different code standard create such bad performance?
    • By Kjell Andersson
      I'm trying to get some legacy OpenGL code to run with a shader pipeline,
      The legacy code uses glVertexPointer(), glColorPointer(), glNormalPointer() and glTexCoordPointer() to supply the vertex information.
      I know that it should be using setVertexAttribPointer() etc to clearly define the layout but that is not an option right now since the legacy code can't be modified to that extent.
      I've got a version 330 vertex shader to somewhat work:
      #version 330 uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ModelViewMatrix; layout(location = 0) in vec4 Vertex; layout(location = 2) in vec4 Normal; // Velocity layout(location = 3) in vec3 TexCoord; // TODO: is this the right layout location? out VertexData { vec4 color; vec3 velocity; float size; } VertexOut; void main(void) { vec4 p0 = Vertex; vec4 p1 = Vertex + vec4(Normal.x, Normal.y, Normal.z, 0.0f); vec3 velocity = (osg_ModelViewProjectionMatrix * p1 - osg_ModelViewProjectionMatrix * p0).xyz; VertexOut.velocity = velocity; VertexOut.size = TexCoord.y; gl_Position = osg_ModelViewMatrix * Vertex; } What works is the Vertex and Normal information that the legacy C++ OpenGL code seem to provide in layout location 0 and 2. This is fine.
      What I'm not getting to work is the TexCoord information that is supplied by a glTexCoordPointer() call in C++.
      Question:
      What layout location is the old standard pipeline using for glTexCoordPointer()? Or is this undefined?
       
      Side note: I'm trying to get an OpenSceneGraph 3.4.0 particle system to use custom vertex, geometry and fragment shaders for rendering the particles.
    • By markshaw001
      Hi i am new to this forum  i wanted to ask for help from all of you i want to generate real time terrain using a 32 bit heightmap i am good at c++ and have started learning Opengl as i am very interested in making landscapes in opengl i have looked around the internet for help about this topic but i am not getting the hang of the concepts and what they are doing can some here suggests me some good resources for making terrain engine please for example like tutorials,books etc so that i can understand the whole concept of terrain generation.
       
    • By KarimIO
      Hey guys. I'm trying to get my application to work on my Nvidia GTX 970 desktop. It currently works on my Intel HD 3000 laptop, but on the desktop, every bind textures specifically from framebuffers, I get half a second of lag. This is done 4 times as I have three RGBA textures and one depth 32F buffer. I tried to use debugging software for the first time - RenderDoc only shows SwapBuffers() and no OGL calls, while Nvidia Nsight crashes upon execution, so neither are helpful. Without binding it runs regularly. This does not happen with non-framebuffer binds.
      GLFramebuffer::GLFramebuffer(FramebufferCreateInfo createInfo) { glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); textures = new GLuint[createInfo.numColorTargets]; glGenTextures(createInfo.numColorTargets, textures); GLenum *DrawBuffers = new GLenum[createInfo.numColorTargets]; for (uint32_t i = 0; i < createInfo.numColorTargets; i++) { glBindTexture(GL_TEXTURE_2D, textures[i]); GLint internalFormat; GLenum format; TranslateFormats(createInfo.colorFormats[i], format, internalFormat); // returns GL_RGBA and GL_RGBA glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, createInfo.width, createInfo.height, 0, format, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); DrawBuffers[i] = GL_COLOR_ATTACHMENT0 + i; glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, textures[i], 0); } if (createInfo.depthFormat != FORMAT_DEPTH_NONE) { GLenum depthFormat; switch (createInfo.depthFormat) { case FORMAT_DEPTH_16: depthFormat = GL_DEPTH_COMPONENT16; break; case FORMAT_DEPTH_24: depthFormat = GL_DEPTH_COMPONENT24; break; case FORMAT_DEPTH_32: depthFormat = GL_DEPTH_COMPONENT32; break; case FORMAT_DEPTH_24_STENCIL_8: depthFormat = GL_DEPTH24_STENCIL8; break; case FORMAT_DEPTH_32_STENCIL_8: depthFormat = GL_DEPTH32F_STENCIL8; break; } glGenTextures(1, &depthrenderbuffer); glBindTexture(GL_TEXTURE_2D, depthrenderbuffer); glTexImage2D(GL_TEXTURE_2D, 0, depthFormat, createInfo.width, createInfo.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthrenderbuffer, 0); } if (createInfo.numColorTargets > 0) glDrawBuffers(createInfo.numColorTargets, DrawBuffers); else glDrawBuffer(GL_NONE); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) std::cout << "Framebuffer Incomplete\n"; glBindFramebuffer(GL_FRAMEBUFFER, 0); width = createInfo.width; height = createInfo.height; } // ... // FBO Creation FramebufferCreateInfo gbufferCI; gbufferCI.colorFormats = gbufferCFs.data(); gbufferCI.depthFormat = FORMAT_DEPTH_32; gbufferCI.numColorTargets = gbufferCFs.size(); gbufferCI.width = engine.settings.resolutionX; gbufferCI.height = engine.settings.resolutionY; gbufferCI.renderPass = nullptr; gbuffer = graphicsWrapper->CreateFramebuffer(gbufferCI); // Bind glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); // Draw here... // Bind to textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[0]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textures[1]); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[2]); glActiveTexture(GL_TEXTURE3); glBindTexture(GL_TEXTURE_2D, depthrenderbuffer); Here is an extract of my code. I can't think of anything else to include. I've really been butting my head into a wall trying to think of a reason but I can think of none and all my research yields nothing. Thanks in advance!
    • By Adrianensis
      Hi everyone, I've shared my 2D Game Engine source code. It's the result of 4 years working on it (and I still continue improving features ) and I want to share with the community. You can see some videos on youtube and some demo gifs on my twitter account.
      This Engine has been developed as End-of-Degree Project and it is coded in Javascript, WebGL and GLSL. The engine is written from scratch.
      This is not a professional engine but it's for learning purposes, so anyone can review the code an learn basis about graphics, physics or game engine architecture. Source code on this GitHub repository.
      I'm available for a good conversation about Game Engine / Graphics Programming
  • Popular Now