PDA

View Full Version : best method for skybox



zed
05-05-2006, 05:39 PM
A/ using a cubemap
B/ storing 6 side textures (and binding from 3-5 depending on whats visable)

at the moment im using #A (i have used #B in the past)
on the face of it #A seeems better, its just a single texture bind and closer to what u want as a skybox is a cube.
but im worried about the speed of accessing cubemaps, ie is it slower than a 2d texture, i cant see why not but then again i have no idea what the hardware does.
any comments.

this is important to get right since a skybox has the potentual to cover a large % of the screen

jide
05-05-2006, 05:45 PM
Really ? I really don't know since I always used cubemap and not 6 textures (or one big you cut). But at my point of view, cubemap, as an extension, should be more appropriated for that point. Maybe did you use a single texture ?

There's also spheremap and dual-paraboloid mapping but I know you know them.

jide
05-05-2006, 06:06 PM
Also, did you tried FBO (but maybe you do it in shaders :) Inside FBO it was more fast than doing it directly.

zeoverlord
05-05-2006, 06:12 PM
The fastest thing would probably be to put all six textures in one single texture (not a cubemap), if you do it right, it could be faster and better looking than a cubemap.

Rodrix
05-05-2006, 07:17 PM
I am currently using 6 indepedent textures instead of cubemap and looks real good (with GL_CLAMP) however binding textures depending on the view seems a great approach! (if using a single texture that contains all 6).

...But if you want it to look good you would have to use at least 512x512 and having six textures on a single texture would mean using a 2048x2048 texture (since 512x512 x 6=1536x1536). So that would mean loading to memory a significant number of bytes more than neccesary. Do you think that using this method with big textures would hurt performance!?

Cheers! Rod

Jan
05-06-2006, 01:29 AM
Erm, i mean it's a pretty old extension. I would guess, that accessing a cubemap is faster than doing it in any other way by your own. It certainly is hardware-accelerated, i mean, it has to be, otherwise the GPU would not be able to work in parallel to the CPU.

That means, less state changes and no application overhead. Also, the driver knows how to store 6 textures best. Possibly it stores them in one big array (as one texture) or it stores them as six single textures, but no matter what it does, it knows more about speeding things up, than you do.

I wouldn't waste my time on this. Just go with the cubemap and be happy.

And also, the problem of a skybox is, that it possibly covers a lot of pixels. But there will always be the exact same amount of texture-accesses, no matter if you use a cubemap or 1-5 2D textures. You won't cut it down by not using cubemaps, you will only introduce another few state changes.

The only trick, i can think of, is to render your skybox not as 6 quads, but more finely tesselated, ie. as 4x4 quads per face. This way the GPU might be able to reject quads, that are completely hidden and thus not rasterizing so many fragments.

Jan.

Jan
05-06-2006, 01:30 AM
Originally posted by zeoverlord:
The fastest thing would probably be to put all six textures in one single texture (not a cubemap), if you do it right, it could be faster and better looking than a cubemap. How should it be possible to make it better looking this way??? It's still the same texture!

Jan
05-06-2006, 01:42 AM
zed: If you want to know what the hardware does, read the spec of ARB_cubemap. In fact it handles a cubemap like 6 2D textures. It examines the texture-coordinate triple (x,y,z) and checks which has the biggest absolute value. Then it also checks the sign of that component. So if |x| is biggest and |x| == -x, it selects the the left face. After that, it rescales y and z by dividing it with some value depending on x. After that it accesses the left cubemap face with the new texture-coordinates s' and t' just like any other 2D texture.

So you see, it is only a few instructions PER VERTEX and then you get the full speed of 2D texture-accesses.

Jan.

zed
05-06-2006, 04:35 AM
jide - fbo is totally irrelavant (perhaps youre thinking of an environmap may where the texture perhaps changes), skyboxes generally dont
rodrix - GL_CLAMP (u might wanna look at clamp_to_edge) also check your math ie false->(since 512x512 x 6=1536x1536).
also sides dont have to be square thus for a power of 2 u could use 1024x2048 (ie 2sidesx3sides)

The only trick, i can think of, is to render your skybox not as 6 quads, but more finely tesselated, ie. as 4x4 quads per face. This way the GPU might be able to reject quads, that are completely hidden and thus not rasterizing so many fragments.good idea (for stuff like water etc) but a skybox is a simple shader so u wont save much (i expect)

How should it be possible to make it better looking this way?since cubemaps dont wrap edges u could a slign a couple which may look ok (OTOH u might have 2 discordant sides against each other that make it look worse than a clamp_to_edge)

zed: If you want to know what the hardware does, read the spec of ARB_cubemap.no, thats not what the hardware does but what the spec saiz :) , im pretty sure the hardware guys take liberties with a lotta things in thge spec.
i thought someone might of tested this already?
IIRC from my testing 3d textures are a bit slkower than 2d textures
anyways thanks Jan and the rest

zeoverlord
05-06-2006, 05:05 AM
Originally posted by zed:
jide - fbo is totally irrelavant (perhaps youre thinking of an environmap may where the texture perhaps changes), skyboxes generally dont
rodrix - GL_CLAMP (u might wanna look at clamp_to_edge) also check your math ie false->(since 512x512 x 6=1536x1536).
also sides dont have to be square thus for a power of 2 u could use 1024x2048 (ie 2sidesx3sides)I was thinking more of 3078x512.
However, i am trying to move away from using cubemaps, all though they might look nice it's not exactly what i want to use in the future.
I want them to be animated, and blend in better with the scene.

jide
05-07-2006, 11:03 AM
zed, yes, I confused myself. FBO should really not be of any kind of help here.

Toni
05-07-2006, 12:53 PM
Originally posted by zeoverlord:

Originally posted by zed:
jide - fbo is totally irrelavant (perhaps youre thinking of an environmap may where the texture perhaps changes), skyboxes generally dont
rodrix - GL_CLAMP (u might wanna look at clamp_to_edge) also check your math ie false->(since 512x512 x 6=1536x1536).
also sides dont have to be square thus for a power of 2 u could use 1024x2048 (ie 2sidesx3sides)I was thinking more of 3078x512.
However, i am trying to move away from using cubemaps, all though they might look nice it's not exactly what i want to use in the future.
I want them to be animated, and blend in better with the scene. mmm i think that no mattar how you put 512x512x6 textures that u won't have 1536x1536...
i suppose u meant 1536x1024 if u sort them in a 3x2 way

Toni

Humus
05-07-2006, 01:40 PM
Originally posted by Jan:
The only trick, i can think of, is to render your skybox not as 6 quads, but more finely tesselated, ie. as 4x4 quads per face. This way the GPU might be able to reject quads, that are completely hidden and thus not rasterizing so many fragments.If you mean that each quad is to be rejected in a software step to completely eliminate some hidden stuff, then that may improve performance slightly, but I doubt you'll see a bit increase. If you mean rejected by HiZ or something like that, then it's a bad idea. HiZ works on fragments, not geometry, so all it would do is introduce polygon edges in the image, which would slow things down.

As for skybox tricks, here's a small one I have, which I used in a few samples in the ATI SDK:

/*
Render the skybox in clip-space. We use a big triangle spanning outside
the screen to avoid polygon edges within the screen for a tiny performance
boost. Z is set to constant 1 to put it behind everything.
The texture coordinates for the cubemap is computed by projecting the
clip-space position back into world space with the inverse MVP matrix.
*/
mat4 iMvp = !mvp;

vec4 v0( 0, 2, 1, 1);
vec4 v1( 3, -1, 1, 1);
vec4 v2(-3, -1, 1, 1);

glBegin(GL_TRIANGLES);
glTexCoord4fv(iMvp * v0);
glVertex4fv(v0);
glTexCoord4fv(iMvp * v1);
glVertex4fv(v1);
glTexCoord4fv(iMvp * v2);
glVertex4fv(v2);
glEnd();The vertex shader gets exemplarily simple:

varying vec3 cubeCoord;

void main(){
gl_Position = gl_Vertex;
cubeCoord = gl_MultiTexCoord0.xyz;
}This has zero polygon edges in the skybox. This improves performance about 1% over drawing it with 6 quads, depending on resolution and whether multisampling is used.

SirKnight
05-07-2006, 07:11 PM
I use the method Humus talks about. Works very good.


-SirKnight

Humus
05-08-2006, 02:48 PM
And of course, the most important "trick" is to ensure you draw the skybox last to properly take advantage of HiZ. For some reason lots of games and apps draw the skybox first.

ScottManDeath
05-08-2006, 10:49 PM
I just used cube geometry with a cube map and the texcoords equal to the vertex positions.

charliejay
05-09-2006, 02:24 AM
In the context of both Jan's 4x4 idea, am curious to know whether there is any point where fragments might be generated between the near and far planes, but outside the other planes, thus subsequently being culled, and perhaps causing a performance impact?

Read something in the Red Book (can't remember what, when, or where, of course :-( ) that made me think this was possible, so I thought I'd ask...

charliejay
05-09-2006, 02:40 AM
Second question(s) - Humus's method implies that you can have 3 (or even 4?) different sides of a cubmap being present on one triangle, correct?

If so, does that cause a slowdown, or a variation in performance?

Point of drawing the skybox first was to save you a color buffer clear, I always thought - is this still likely to be useful?

charliejay
05-09-2006, 02:48 AM
PS - "culled", in my first post, means on a per fragment level.

knackered
05-09-2006, 03:07 AM
Originally posted by charliejay:
Point of drawing the skybox first was to save you a color buffer clear, I always thought - is this still likely to be useful? An explicit buffer clear is always quicker than rendering a poly. And if you're using a sky box you only need to clear the depth buffer at start of render, then render the sky box after all opaque objects, but before any transparent objects.

Humus
05-09-2006, 05:40 AM
Originally posted by charliejay:
Second question(s) - Humus's method implies that you can have 3 (or even 4?) different sides of a cubmap being present on one triangle, correct?

If so, does that cause a slowdown, or a variation in performance?Even 5. ;) Sure, 5 sides being visible at the same time may slow things down a bit, but that's no different than if you put it in several different textures. It's still the same amount of data that needs to be passed. Performance will vary with the way you look, looking into the corners of the cubemap is generally slower than looking at a single face, due to filtering and such (say trilinear vs. linear magnification).


Originally posted by charliejay:
Point of drawing the skybox first was to save you a color buffer clear, I always thought - is this still likely to be useful? No. It was never really useful. The clear is not needed, regardless if you draw the skybox first or last. You may still want to use a clear though, especially on modern hardware that has fast color clear and compression techniques, so you may want to clear just to get clean caches, just like for Z.

Humus
05-09-2006, 05:46 AM
Originally posted by charliejay:
In the context of both Jan's 4x4 idea, am curious to know whether there is any point where fragments might be generated between the near and far planes, but outside the other planes, thus subsequently being culled, and perhaps causing a performance impact?

Read something in the Red Book (can't remember what, when, or where, of course :-( ) that made me think this was possible, so I thought I'd ask... Not sure what you mean. With my method above the Z will always end up as 1, pegging it exactly on the far plane. But if you have user clip planes those can certainly cull off fragments, for instance I guess you could use a clip plane to cut off stuff below the terrain/water to improve performance a bit.

Jan
05-09-2006, 11:52 AM
"so you may want to clear just to get clean caches"

Caches? What exactly do you mean? Is there any benefit of clearing the color-buffer over ... you know ... not doing it?

Jan.

Humus
05-09-2006, 02:30 PM
Caches maybe isn't the right word, but it's the same as with the depth buffer. If you don't clear the depth buffer, performance will suffer after a number of frames as blocks get uncompressed where needed and left in a dirty state. When you clear you get a clean start not impacted by previous rendering. With fast Z clear it's essentially free to clear anyway, so there's no reason not to do it. If you never clear, eventually all blocks are left uncompressed and you end up more or less as if you had no HiZ. The same with color clear. On cards that support color compression it's best to clear, or you'll essentially get the same performance as if there was no color compression.

Jan
05-09-2006, 05:08 PM
I assume the Radeon 9700 Mobility already does so? Well, just now i cannot see a difference, but that might be difficult to produce.

So, would it be best to clear color every frame, or only to clear, say every 5 frames?

Rodrix
05-09-2006, 08:56 PM
Hi guys!
Yeah about the 512x512 x 6 I guess I meant = 1536x1024... Anyways, what do you expect from Microsoft's calculator! haha :p

Another problem that you all might share with me:
Most games use a skybox and place a plane through the middle of the skybox representing the world floor. As a consequence, half of the textures on the sides of the skybox cube are not used in the game since the player walks on top of the plane floor. Their sum represent 4 complete faces of texture, which is a complete waste.

Would you then draw half a cube instead of the complete cube skybox?

And if yes, you can use a 1024x512 texture for you cube sides, right?! (suppposing your top skybox texture is 1024x1024)
1024x512 is a valid power of 2 size right?! or not-square sizes can also be used but also reduce performace compared to square sizes?

Thanks!
Cheers! :D
Rod

zed
05-10-2006, 01:03 AM
Humus im curious why u have with that example the opposite polygon winding
eg with standard gl state
glCullFace( GL_BACK );
glFrontFace( GL_CCW );
nothing will show up


And if yes, you can use a 1024x512 texture for you cube sides, right?!i assume not, as cubes have all sides of the same length,
also with 1536x1024 1536 is not a power of 2 it must be 1024 or 2048 (unless u use texture_rectangle or NPOT textures)
also WRT 'Most games use a skybox and place a plane through the middle of the skybox representing the world floor' this is only valid if the ground is a plain (which in 99% of cases is not true)

charliejay
05-10-2006, 01:03 AM
Hi Humus,

Have remembered the context of what I was thinking of...

I read somewhere (in the Red Book, I think), that the viewport can be bigger than the actual drawable area, resulting in the generation of fragments that never get drawn.

Now that I've remembered the context, it becomes a non-issue, since my viewports will generally fit the drawable area exactly...

Rodrix
05-10-2006, 10:12 AM
Originally posted by zed:



And if yes, you can use a 1024x512 texture for you cube sides, right?!i assume not, as cubes have all sides of the same length,
also with 1536x1024 1536 is not a power of 2 it must be 1024 or 2048 (unless u use texture_rectangle or NPOT textures)
also WRT 'Most games use a skybox and place a plane through the middle of the skybox representing the world floor' this is only valid if the ground is a plain (which in 99% of cases is not true) [/QB]I guess I didn't explain right. It's also difficult to put in words.

In my particular case I am using a plain floor. So in my particular case, the user never gets to see the the bottom half parts of the sides of my skybox cube, nor the bottom of the cube, as I got a plane floor that goes through the exact middle of the cube. That is, my visible sky texture surround is not a cube any more, but half a cube, or a square of size A and and depth A/2.

The question was that if consider only drawing the polygons for the visible part, what texture sizes should I use. The sides of my sky paralelepid would be AxA/2 or let's say 1024x512.

So, should I use 1024x512 textures for my paralepid sides, or a 1024x1024 texture that is then stretched to 1024x512 on render? My concern is that if the fact that the texture is not square may reduce performance? ('power of 2 textures')

Now for the 99% rest of the cases, even though the floor is not plain, great part of the textures are not seen since they are beneath the floor, or view, right? The illusion of the skybox is maintained if the camera is near the center of the cube, and if the player is walking, not flying, why is the half bottom of the cube necessary!? (Am i missing something?!)

Thanks! The question is kind of confusing. I hope you understand it!

Rod

Madoc
05-10-2006, 11:59 AM
If you know the bottom half of your cube-map will never be visible, then sure you can do that. There won't be any penalty for a rectangular texture (at least not on any OpenGL implementation that I know). Of course you'll have to use standard 2D textures and not a cube-map. I would reccomend keeping the textures separate rather than trying to merge them and have wasted space (unless you can page something else on there). Even if you don't manually cull your cube faces, the hardware will typically not do anything with you texture bind until it effectively needs to draw some fragments with it (at least in this case, afaik). So, the hardware will do the culling that counts for you.

You probably won't gain much if you're already drawing your skybox after the ground but it should be a win.

Humus
05-11-2006, 08:44 AM
Originally posted by Jan:
I assume the Radeon 9700 Mobility already does so? Well, just now i cannot see a difference, but that might be difficult to produce.

So, would it be best to clear color every frame, or only to clear, say every 5 frames? I'm not sure exactly what cards has it, but I don't think the Mobility 9700 has it. At least I typically see a slight slowdown on my laptop when I clear, while it's the other way around on the X1900.
Exactly how often you clear isn't neccesarily written in stone, but every frame is a safe bet. It's very cheap anyway.

Humus
05-11-2006, 08:47 AM
Originally posted by zed:
Humus im curious why u have with that example the opposite polygon winding
eg with standard gl state
glCullFace( GL_BACK );
glFrontFace( GL_CCW );
nothing will show upWell, my preference has always been that frontfaces are clockwise, so my framework always calls glFrontFace(GL_CW) at startup.

Ynaig
05-14-2006, 05:50 PM
Humus,

Will your method for drawing skyboxes work for outer space environments (scifi stuff)?

Also I think drawing it last is a bad idea if you have transparent textures on some models.

Ynaig

zed
05-14-2006, 07:33 PM
Will your method for drawing skyboxes work for outer space environments (scifi stuff)?well theres no diff what the textures are, be it space/sky/underwater etc. im using it for mostly space stuff as it happens

Also I think drawing it last is a bad idea if you have transparent textures on some models.use the following order
draw solid meshes
draw skybox
draw transparent stuff (translucent) with depth writes off

Ynaig
05-14-2006, 09:55 PM
Problem is that if I use different z domains for different group of objects that never overlap, then drawing the skybox last will not work in this case cause I usually clear the z depth before every z domain. Cause there's different scales for different group of objects.

Ynaig

Humus
05-15-2006, 06:07 PM
Well, in that case I guess you could use the stencil buffer instead. Clear to zero and tag stencil to 1 for everything you draw. Then draw the skybox in the end with the stencil test rejecting stencil != 0. I'm not sure how much gain you'd see from that though, but if you have a reasonable amount of skybox hidden normally it may be worth a try.