best method for skybox

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

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.

Also, did you tried FBO (but maybe you do it in shaders :slight_smile: Inside FBO it was more fast than doing it directly.

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.

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

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.

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!

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.

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 :slight_smile: , 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

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.

zed, yes, I confused myself. FBO should really not be of any kind of help here.

Originally posted by zeoverlord:
[quote]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.
[/QUOTE]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

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.

I use the method Humus talks about. Works very good.

-SirKnight

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.

I just used cube geometry with a cube map and the texcoords equal to the vertex positions.

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 :frowning: ) that made me think this was possible, so I thought I’d ask…

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?

PS - “culled”, in my first post, means on a per fragment level.

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.