simple skybox/-sphere - don't know how

Hi there,

I want to have a skybox or skysphere in my scene. The Picture itself is not that important, but a starfield would be best.

In theory I would put that image as a texture on a cube or sphere. That cube/sphere must be so big that my camera can zoom inside. But the problem I see is that the texture will only be seen from the outside and not from the inside.

Excuse me if I’m wrong, but I never used texturing before and wasn’t able to find simple information on skyboxes in the forum.

So, create your box or sphere model inside-out. Or use:

nodePath.set_two_sided(true);

to make it visible from both sides.

Although you can achieve what you want by making a box or sphere that is large enough to include your entire environment, this usually isn’t the best way to make a skybox. The problem with a really big box like this is that it is in danger of being clipped by your far clipping plane, which means you need to push your far plane out farther than the box. You can do that, too, but it diminishes your Z depth.

A better solution is to have a small box, really any size at all, and draw it first in the scene, without writing to the depth buffer. This would look like this:

nodePath.set_bin("background", 0);
nodePath.set_depth_write(false);

Make sure the box is parented to the camera. You can also set a CompassEffect so it will spin around with the world automatically:

nodePath.set_compass();

David

Did not though about the compass trick. Always used my own task for that. Thanks!

Thank you drwr. That sounds good. I tried to implement it, but I still have some trouble with adding a texture to my NodePath (or let me say find the c++ names of the necessary python functions…).

I have this NodePath that will be my skybox (a scratch):

NodePath skybox = NodePath("skybox");
skybox = pWindow->load_model(pFramework->get_models(), "box");

(By the way: is there an synonym to pythons “loader.load_model(“filename”)” in c++, I mean its just a wrapper isn’t it?)

In the manual they say:

Texture tex = loader.loadCubeMap("");

How is it done in C++?

@drwr:
what is nodePath.set_bin(…) for? I didn’t find it in the C++ Reference of NodePath. Is your parameter “background” an imagefile like “skybox.png” ?

If I have a Texture tex, how can I admit it to my NodePath?

I’m sorry, this all looks like being very basic but I was not able to find something suitable in the forums via search and time is running…

pWindow->load_model() in C++ is the closest approximation to loader.loadModel() in Python. It’s just a wrapper, sure, but it’s kind of a heavy wrapper; and WindowFramework::load_model() more-or-less does the same thing. You could, of course, avoid the wrapper and make the underlying call to Loader::load_sync() yourself; see the code in windowFramework.cxx.

For loader.loadTexture(), you should use the TexturePool, e.g. PT(Texture) tex = TexturePool::load_texture(“mytex.png”). If you really want to load a cube map, use TexturePool::load_cube_map(“mytex_#.png”).

Hmm, the C++ API reference seems to be missing many methods of NodePath. I don’t know why. But set_bin() is for controlling render order, and the name “background” is the name of one of the standard bins. This is documented in the manual on the page “How to control render order”.

David

ok. the picture I see is the following:

I admit that I have not really understood the procedure you’ve described above.

This is my code:

this->skyBox_texture = TexturePool::load_texture("skymap_0.png");
	this->skyBox.set_texture(skyBox_texture);
	this->skyBox.set_bin("background", 0);
	this->skyBox.set_depth_write(false);
	this->skyBox.set_compass();
	this->skyBox.reparent_to(pWindow->get_render());

/* adding the camera node */

What is your skybox model? Are you sure that it is a box centered on the origin? Does it have sensible UV’s?

Is your skybox modeled with six faces and 2-D UV’s for six different textures, or is it modeled with six faces and 3-D UV’s for a single cube map? If you don’t understand the difference, you should review the section on texturing in the manual.

Right now, you are applying a single 2-D texture to the entire box, which is probably not correct, unless your skybox has UV’s designed for this and your 2-D texture is specifically painted for this. In the screenshot, I see the “gradient” texture, which appears to have been applied to a card (or possibly to a box not centered at the origin) and to a wireframe smiley. I have no idea which of these is your skybox model, but neither of them is designed to receive a texture like “gradient” over the whole surface.

You can’t just use any old geometry for a skybox. Your geometry has to be specially constructed to display the texture you painted, to wrap around its surface in the correct way according to the way you painted it.

David

I’m sorry that I didn’t mention any details. The box you see is my skybox. I loaded the standard “box.bam.pz” from the panda model directory, so I don’t know its specifications.

The spheres you see are planets in my scene, self generated spheres / isocahedrons. The aren’t center of interest for this problem.

So am I right in expecting to create a cube out of 8 vertices and 6 sides (1 square not 2 triangles) to put a 6-part-texture loaded with TexturePool::load_cube_map(…) on it?

The “box” model that ships with Panda has one vertex on the origin; it is not centered on the origin. If you wish to use this box you will have to reposition it. It also lacks 3-D UV’s which are required for a cube map; if you wish to use this box you will have to create UV’s for it, for instance as described in the manual.

But you are probably better constructing your own box to meet your precise needs. Constructing a box is easy and it will be helpful to understand the whole process.

It doesn’t matter whether your box has 1 square or 2 triangles for each face (they’ll be turned into triangles anyway). It also doesn’t matter whether you share the vertices at the corners or not (chances are they will need to be replicated when it is loaded anyway, depending on your precise construction; but there’s not a big difference one way or another).

The important points are: (1) you need to have the center at the origin, (0, 0, 0), and (2) you need to have UV’s that match your texture. If you are applying a cube map, that means you need to have 3-D UV’s at each vertex that correspond to the 3-D position of the box. Not all egg converters support 3-D UV’s, so this might be a problem depending on your modeling package of choice, and you might need to create 3-D UV’s at runtime anyway (as described in the manual).

But you don’t need to use a cube map; in fact, I wouldn’t recommend it. I would just create a box with six different 2-D textures applied to it, one for each face. If you apply the textures within the modeling package, then you don’t need to apply them at runtime, and it’s just a simple matter of loading the box and parenting it to the camera.

If you have different sky textures, create a different box for each one.

David

Thanks a lot. I will have a try now. Just to mention it I have to say that my favourite modelling tool is blender. Give me some time…

Hi drwr,

I modelled a box thats placed in the origin in Blender and admittet a texture to it in UV-Mode. Then I exported it to .egg.

Here is an extract from the .egg-file:

<Material> Material {
  <Scalar> diffr {0.800000011921}
  <Scalar> diffg {0.800000011921}
  <Scalar> diffb {0.800000011921}
  <Scalar> specr {0.25}
  <Scalar> specg {0.25}
  <Scalar> specb {0.25}
  <Scalar> shininess {12.5}
}
<Texture> skybox_Cube.tga {
  "./../models/skybox_Cube.tga"
  <Scalar> saved-result { 1 }
  <Scalar> envtype { MODULATE }
  <Scalar> minfilter { LINEAR }
  <Scalar> magfilter { LINEAR }
  <Scalar> wrap { REPEAT }

The structure in my binary-directory is the following:

ReleaseFast/
  models/
  textures/
  MyProgram.exe

The model is saved to “ReleaseFast/models/skybox.egg”. You find the texture in “ReleaseFast/textures/skybox_Cube.tga”

Unfortunately I cannot see the texture in Panda. Everything I see is black (Is it the material? No because it is nearly white, isn’t it?):

My code hasn’t relly changed:

this->skyBox = pWindow->load_model(
		pFramework->getPandaFramework()->get_models(),
		"models/skybox.egg");

	this->skyBox_texture = TexturePool::load_texture("textures/skybox_Cube.tga");
	this->skyBox.set_texture(skyBox_texture);
	this->skyBox.set_bin("background", 0);
	this->skyBox.set_depth_write(false);
	this->skyBox.set_compass();
	this->skyBox.reparent_to(pWindow->get_render());

If I have already linked the texture to the mesh in the .egg-file as you see, is there still the need to load it in panda like I am doing it?