How to render skybox to all the cameras?

OK, here is my shader:

#version 150

uniform mat4 p3d_ModelMatrix;
uniform mat4 p3d_ViewProjectionMatrix;

in vec4 p3d_Vertex;
in vec2 p3d_MultiTexCoord0;

out vec2 texcoord;

void main() {
  mat4 model = p3d_ModelMatrix;
  mat4 proj = p3d_ViewProjectionMatrix;

  // Reset position to zero both for skybox and camera
  model[3] = vec4(0, 0, 0, 1);
  proj[3] = vec4(0, 0, 0, 1);

  gl_Position = proj * (model * p3d_Vertex);
  texcoord = p3d_MultiTexCoord0;
}

Maybe it’s not an optimal way to do it, but it is here. Thanks Thaumaturge and rdb for their help.

Next I’ll try this method:

one alternative approach is just to render a fullscreen quad behind everything and just do the projection of the cube map entirely in the shader itself.

1 Like

It looks that they are placed outside the bounding volume. I need to check the source code.

When the object on which I project the cubemap texture is bigger than the skybox, skybox projection dissapears from the reflection.

So neither my shader, nor duplicating spheres solve this particular issue.

I’ll have to try the second method suggested by rdb.

I don’t know what you mean. Outside the bounding volume of what object? The six cameras are all placed on the same point, which is the point you tell Panda to render from.

If the skybox is not visible, then it may be too small and inside the near distance of the cameras, or because you have forgotten to disable view culling on the sky object.

Outside the bounding volume of what object?

I mean the object I am rendering the reflection to. Sorry, forgot to clarify.

The six cameras are all placed on the same point, which is the point you tell Panda to render from.

OK! Then it’s not the source of the problem.

If the skybox is not visible, then it may be too small and inside the near distance of the cameras, or because you have forgotten to disable view culling on the sky object.

It becomes invisible (on the cubemap only, not on the main window!) only if the object in question (that is used for makeCubemap) is bigger than the skybox. The object is hidden for the rig cameras using the camera bitmask.

As I understand, culling for the node is disabled like this (I found this in your post on the panda forums):

skybox.node().setBounds(OmniBoundingVolume())
skybox.node().setFinal(True)

Is this correct?

Yes, it is.

Ah! I wonder if this is a depth testing problem? Have you tried this?

skybox.setDepthWrite(False)
skybox.setDepthTest(False)
skybox.setBin("background", 0)

You should also make sure that the skybox is larger than the near distance of the cubemap camera.

Ah! I wonder if this is a depth testing problem? Have you tried this?

Yes, I’ve already set this.

You should also make sure that the skybox is larger than the near distance of the cubemap camera.

It is. The size op the skydome and the size of the object to which I apply makeCubemap method, they are relative numbers. E.g. if the skydome is 15 units in width/height, and the object is 20, it will produce the same incorrect image as with 150/200 and 1500/2000 and so on.

To understand what I am talking about, the sphere of this size (15 units) is rendereed without shader on the 1st image and with shader and depth test off on the second. The teapot is 20 units in width/length (Edit: probably more by the looks of it).

I’ve also inspected the contents of each camera’s framebuffer (of those that render the cubemap), and it looks like the sphere is rendered for them slightly away in the direction of the front vector of the camera, for 4 of the side cameras.

It doesn’t depend on the distance between zero coordinates, where the skybox is rendered, and the object (teapot) itself.

Maybe it has to do something with w component of the translation vectors I set in the shader? I set it to 1, maybe I shouldn’t.

I found what was the problem there.

I relied on this manual page:
https://docs.panda3d.org/1.10/python/programming/render-to-texture/dynamic-cube-maps

The example code tells to reparent the rig nodepath to the teapot. For the example, it works right. For me, it creates an offset. Though I don’t understand why it does so.

If I reparent the rig to the root node, it won’t create this offset.

E.g. this code produces a correct cubemap:

rig.reparentTo(render)
rig.setPos(teapot.getPos())

This doesn’t:

rig.reparentTo(teapot)

I don’t understand why though.

Does “rig” perhaps have a position already when it’s parented to the teapot? That might result in an offset, if I’m not much mistaken.

(That is, what is the output of printing “rig.getPos()” directly before reparenting it to the teapot?)

It doesn’t.

rig = NodePath("rig")
print(rig.getPos())
rig.reparentTo(teapot)
print(rig.getPos())

Output:

LPoint3f(0, 0, 0)
LPoint3f(0, 0, 0)

Also:

for cam in rig.getChildren():
	print(cam.getPos())

Output:

LPoint3f(0, 0, 0)
LPoint3f(0, 0, 0)
LPoint3f(0, 0, 0)
LPoint3f(0, 0, 0)
LPoint3f(0, 0, 0)
LPoint3f(0, 0, 0)

Hmm… I’m not sure, then. I imagine that there’s likely something in your setup that’s producing the difference, but I don’t know what it is, offhand. :/

You are right, I think. The scale attribute of the teapot propagates down and messes with the cameras somehow. I assumed they are just points in space and cannot be affected by scale.

Ah, right, no: a scale can indeed mess with things somewhat. I’m not sure of exactly how scaling affects cameras, but I would guess that it could factor into their projection matrices at the least.

If you have a model that you want scaled, you could perhaps parent it and the camera setup separately below a common node–that should allow you to scale the model without affecting the cameras. When you want to move the whole setup you could then simply move the common parent, thus moving both the model and the camera setup along with it.

I think it is more than that, I also need to check the teapot (or any object with reflections) has no scale, or if it does, then the rig node has to be 1/objectScale, because it also affects projection.

Possibly; I don’t know. I’m not terribly familiar with cubemaps, I’m afraid. I’ll thus leave it to others to perhaps respond to that!

If you could post your sample code in a form I can run, it would be easier for me to investigate what is going on here.

Thank for your offer, rdb, but I’ve already narrowed down the problem, thanks.

If anyone interested, here’s what was causing the issue:

  1. Not related to cubemaps at all. Parenting 6 cubemap cameras to a scaled NodePath applies scale to cameras’ node paths, obviously.
    In its turn, camera’s scale affects the view matrix, and the resulting image becomes distorted. (Also, scale affects camera’s near/far plane, but this doesn’t concern me now).

  2. For some reason, more correct cubemaps for the objects are created if I place the 6 cameras not at the object coordinates, but 1 unit down. I am not sure if this is a universal case or depends on the model origin.

To solve problem 1 I had to reset view matrix scale in the skybox shader:

  mat4 view = p3d_ViewMatrix;
  view[0] = normalize(view[0]);
  view[1] = normalize(view[1]);
  view[2] = normalize(view[2]);

To solve problem 2, I currently just move the camera 1 unit down the Z axis.

I’ll post code soon if anyone is interested.

1 Like