Cube map has duplicate face

Edit: I got a friend to run this, and he did not have the issue I described. Also, I have clarified that the issue is not in the shaders but rather in the cube map capturing.

Edit2: I have taken out all the camera control code to make the source below shorter. Hit v to view the 6 buffers, and the first and last show the same for me! Also, if I use base.saveCubeMap, it produces the correct result, so I suspect it is in the actual generation of the cube map. Here is some massive log spam from the app: http://fg.98115.net:4520/~max/temp/Panda/fatlog.txt

I take a sphere, shade it with a shader, and capture a cube map viewed from within it. I then display the cube map on the sphere, and one face is a copy of another. The +x face shows a copy of the -z face.

I can’t understand how I could do this if I wanted to, nor have I any idea in the slightest of what can be done to fix it.

Here is a zip of a slimmed version of the project with only the basics to show the issue: fg.98115.net:4520/~max/temp/Pand … fCopy2.zip

Here is the python code: (It’s a mess!)
Specifically look at the getTex function at the top and the 4 lines in init:

    texModel=getModel("sphere") 
    tex1=getTex(texModel,getShader("CubeData1")) 
    
    self.earth.setTexture(tex1) 
    self.earth.setShader(getShader("CubeDisplayData")) 

here is the full code, including those 4 lines.

import direct.directbase.DirectStart
from direct.showbase import DirectObject
from direct.interval.IntervalGlobal import *
from direct.gui.DirectGui import *
from direct.showbase.DirectObject import DirectObject
from direct.task.Task import Task
from pandac.PandaModules import *
import sys

font = loader.loadFont("cmss12")
def addInstructions(pos, msg):
    return OnscreenText(text=msg, style=1, fg=(1,1,1,1), font = font,
                        pos=(-1.3, pos), align=TextNode.ALeft, scale = .05)

def getTex(model,shader):
  rig = NodePath('rig')
  altBuffer=base.win.makeCubeMap("CubeBuff", 1, rig)
  print rig.ls()
  altRender=NodePath("new render")
  
  rig.reparentTo(altRender)
  
  myNode = model
  myNode.reparentTo(altRender)
  myNode.setPos(0,0,0)
  myNode.setScale(100)#Make surface outside nearDist of cams
  myNode.setShader(shader)	
  myNode.setTwoSided(True)
  
  base.graphicsEngine.renderFrame()
  
  #This works correctly
  #base.saveCubeMap('planet_cube_#.jpg', size = 32, source=altBuffer, camera=rig )
  
  #The +x face produced here is a copy of the -z face,
  tex = altBuffer.getTexture()
  
  altBuffer.setActive(False)
  return tex
  
def getShader(name):
  return loader.loadShader("Shaders/"+name+".sha")

def getModel(name):
  return loader.loadModel('models/'+name)

class World(DirectObject):
  #Macro-like function used to reduce the amount to code needed to create the
  #on screen instructions
  def genLabelText(self, text, i):
    return OnscreenText(text = text, pos = (-1.3, .95-.05*i), fg=(1,1,1,1),
                       align = TextNode.ALeft, scale = .05, mayChange = 1)
  def __init__(self):
    self.inst1 = addInstructions(0.95, "Press ESC to exit. Press V to view buffer.")
  
    #The standard camera position and background initialization
    base.setBackgroundColor(0, 0, 0)
    base.disableMouse()
    camera.setPos ( 0, -5, 0 )
    camera.setHpr ( 0, 0, 0 )
   
    self.earth=getModel("sphere")
    self.earth.reparentTo(base.render)    
    
    self.camNode=self.earth.attachNewNode("camNode")
    camera.reparentTo(self.camNode)
    
    texModel=getModel("sphere")
    tex1=getTex(texModel,getShader("CubeData1"))
    
    self.earth.setTexture(tex1)
    self.earth.setShader(getShader("CubeDisplayData"))
    
    # Panda contains a built-in viewer that lets you view the results of
    # your render-to-texture operations.  This code configures the viewer.
    self.accept("escape", sys.exit, [0])
    self.accept("v", base.bufferViewer.toggleEnable)
    self.accept("V", base.bufferViewer.toggleEnable)
    base.bufferViewer.setPosition("llcorner")
    base.bufferViewer.setCardSize(0.1, 0.0)

  #end __init__
#end class world

w = World()

run()

and here are the shaders:
Data shader:

//Cg

void vshader(
    uniform float4x4 mat_modelproj,
    in float4 vtx_position: POSITION,
    out float4 l_position: POSITION,
    out float4 l_pos)
{
    l_pos=vtx_position;
    l_position = mul(mat_modelproj, vtx_position);
}


void fshader(
    in float4 l_pos,
    out float4 o_color: COLOR)
{
	o_color=l_pos/2+.5;
}

and the display shader:

//Cg 

void vshader( 
  in uniform float4x4 mat_modelproj, 
  in float4 vtx_position: POSITION, 
  in float2 vtx_texcoord0 : TEXCOORD0, 
  in float4 vtx_color: COLOR, 
  out float4 l_position: POSITION, 
  out float4 l_pos: TEXCOORD0) 
{ 
  l_pos=vtx_position;  
  l_position = mul(mat_modelproj, vtx_position); 
} 





void fshader( 
  in uniform samplerCUBE tex_0: TEXUNIT0, 
  in float4 l_pos: TEXCOORD0,
  out float4 o_color: COLOR) 
{ 
  float4 data=texCUBE(tex_0,normalize(l_pos.xyz));
  o_color=data;
} 

Any idea of how I can fix the defective face on my cube map? Can any one else reproduce this?

Pro, you said you will look into that because you can reproduce the problem any luck?

I’m still looking for a solution, but finding nothing.

Hm, I’m looking into the problem. In the meantime, you can specify “True” as fifth parameter to makeCubeMap - this will make it copy the texture to RAM every frame (like saveCubeMap does), which will be very slow, but it will work correctly.

Well, considering that I’m only generating cube maps once, not every frame, and I am already copying one of my 2 maps to ram anyway, this solution is quite acceptable, and seems to work great! I can’t seem to specify the to_ram bool by name (it complains about the wrong number of parameters) so I have to pass something for the camera_mask, but 1 seems to work fine.

Not quite an optimal fix, but it works fine in my case! Thanks, and good luck finding the cause and fixing it. It is so nice for my planets to not have the botched face anymore.