Thread: Cube map is upside down.

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    Cube map is upside down.

    After messing some more with my little space game I noticed that my real-time cube maps are upside down. In other words what should be reflected in the top is being reflected in the bottom of the object.

    So if you fly over a planet you will see the reflection of the planet in the top of the spacecraft and in the bottom you will see the reflection of the starfield.

    Any ideas why?

    This is a shader I pulled out of Frank Luna's book but something is amiss with it.
    I added fog into it which is computed in another shader and isn't relevant to the problem.

    Code:
    //=============================================================================
    // EnvMap.fx by Frank Luna (C) 2004 All Rights Reserved.
    //
    // Does Phong lighting and texturing and reflection via an environment map.
    //=============================================================================
    #include "Fog.fx"
    
    struct Mtrl
    {
    	float4 ambient;
    	float4 diffuse;
    	float4 spec;
    	float  specPower;
    };
    
    struct DirLight
    {
    	float4 ambient;
    	float4 diffuse;
    	float4 spec;
    	float3 dirW;  
    };
    
    uniform extern float4x4 gWorld;
    uniform extern float4x4 gWorldInvTrans;
    uniform extern float4x4 gWVP;
    uniform extern Mtrl     gMtrl;
    uniform extern DirLight gLight;
    uniform extern float3   gEyePosW;
    uniform extern texture  gTex;
    uniform extern texture  gEnvMap;
    
    // How much does the surface reflect?  Normally this should be a
    // property of the material since it may vary over a surface.
    static float gReflectivity = 2.0f;
    
    
    sampler TexS = sampler_state
    {
    	Texture = <gTex>;
    	MinFilter = LINEAR;
    	MagFilter = LINEAR;
    	MipFilter = LINEAR;
    	AddressU  = WRAP;
        AddressV  = WRAP;
    };
    
    sampler EnvMapS = sampler_state
    {
    	Texture = <gEnvMap>;
    	MinFilter = LINEAR;
    	MagFilter = LINEAR;
    	MipFilter = LINEAR;
    	AddressU  = WRAP;
        AddressV  = WRAP;
    };
     
    struct OutputVS
    {
        float4 posH    : POSITION0;
        float3 normalW : TEXCOORD0;
        float3 toEyeW  : TEXCOORD1;
        float2 tex0    : TEXCOORD2;
    };
    
    OutputVS EnvMapVS(float3 posL : POSITION0, float3 normalL : NORMAL0, float2 tex0: TEXCOORD0)
    {
        // Zero out our output.
    	OutputVS outVS = (OutputVS)0;
    	
    	// Transform normal to world space.
    	normalL = normalize(normalL);
        outVS.normalW = mul(float4(normalL, 0.0f), gWorldInvTrans).xyz;
    	
    	// Transform vertex position to world space.
    	float3 posW  = mul(float4(posL, 1.0f), gWorld).xyz;
    	
    	// Compute the unit vector from the vertex to the eye.
    	outVS.toEyeW = gEyePosW - posW;
        //outVS.toEyeW = posW - gEyePosW;
    	
    	// Transform to homogeneous clip space.
    	outVS.posH = mul(float4(posL.xyz - float3(0.5f,0.5f,0.5f), 1.0f), gWVP);
    	
    	// Pass on texture coordinates to be interpolated in rasterization.
    	outVS.tex0 = tex0;
    	ComputeFog(float4(posL,1.0f));
    
    	// Done--return the output.
        return outVS;
    }
    
    float4 EnvMapPS(float3 normalW : TEXCOORD0, 
                    float3 toEyeW  : TEXCOORD1, 
                    float2 tex0    : TEXCOORD2) : COLOR
    {
    	// Interpolated normals can become unnormal--so normalize.
    	normalW = normalize(normalW);
    	toEyeW  = normalize(toEyeW);
    	
    	// Light vector is opposite the direction of the light.
    	float3 lightVecW = -gLight.dirW;
    	
    	// Compute the reflection vector.
    	float3 r = reflect(-lightVecW, normalW);
    	
    	// Determine how much (if any) specular light makes it into the eye.
    	float t  = pow(max(dot(r, toEyeW), 0.0f), gMtrl.specPower);
    	
    	// Determine the diffuse light intensity that strikes the vertex.
    	float s = max(dot(lightVecW, normalW), 0.0f);
    	
    	// Get the texture color.
    	float4 texColor = float4(0.0f,0.0f,0.0f,1.0f); //tex2D(TexS, tex0);
    	
    	// Get the reflected color.  
    	float3 envMapTex = reflect(-toEyeW, normalW);
    	float3 reflectedColor = texCUBE(EnvMapS, envMapTex);
    
    	// Weighted average between the reflected color, and usual
    	// diffuse/ambient material color modulated with the texture color.
    	float3 ambientMtrl = gReflectivity*reflectedColor + (1.0f-gReflectivity)*(gMtrl.ambient*texColor);
    	float3 diffuseMtrl = gReflectivity*reflectedColor + (1.0f-gReflectivity)*(gMtrl.diffuse*texColor);
    	
    	// Compute the ambient, diffuse and specular terms separately. 
    	float3 spec = t*(gMtrl.spec*gLight.spec).rgb;
    	float3 diffuse = s*(diffuseMtrl*gLight.diffuse.rgb);
    	float3 ambient = ambientMtrl*gLight.ambient;
    	
    	float3 final = ambient + diffuse + spec;
    		
    	// Output the color and the alpha.
        float4 color = float4(final, gMtrl.diffuse.a*texColor.a);
    
        return color;
    }
    
    technique EnvMapTech
    {
        pass P0
        {
            // Specify the vertex and pixel shader associated with this pass.
            vertexShader = compile vs_2_0 EnvMapVS();
            pixelShader  = compile ps_2_0 EnvMapPS();
        }
    }
    This looks suspect to me:
    Code:
                    // Light vector is opposite the direction of the light.
    	float3 lightVecW = -gLight.dirW;
    	
    	// Compute the reflection vector.
    	float3 r = reflect(-lightVecW, normalW);
    I tried negating these but it didn't fix it.

    The C++ code to render the cube map:
    Code:
    while (iter != end)
        {
            CubeMapEntry * pEntry = iter->second;
            GameObject *pObject = SpaceXApp::GetInstance()->GetGameSector()->Get(pEntry->GameObjectName);
            D3DXVECTOR3 vecPos = pObject->GetOrientControl()->GetPosition();
            
            HRESULT hr = 0;
            if (FAILED(hr = m_pRenderToCube->BeginCube(pEntry->pCubeTexture)))
            {
                OutputDebugString(DXGetErrorString(hr));
                ::MessageBox(0,"Cannot begin cube map rendering",0,0);
            }
    
            for (unsigned int i = 0; i < 6; ++i)
            {
                
                vecLookAt = D3DXVECTOR3(0.0f,0.0f,0.0f);
                vecUp = D3DXVECTOR3(0.0f,1.0f,0.0f);
    
                switch (i)
                {
                    case D3DCUBEMAP_FACE_POSITIVE_X:
                        vecLookAt   = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
                        vecUp       = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
                        break;
                    case D3DCUBEMAP_FACE_NEGATIVE_X:
                        vecLookAt   = D3DXVECTOR3(-1.0f, 0.0f, 0.0f);
                        vecUp       = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
                        break;
                    case D3DCUBEMAP_FACE_POSITIVE_Y:
                        vecLookAt   = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
                        vecUp       = D3DXVECTOR3(0.0f, 0.0f, -1.0f);
                        break;
                    case D3DCUBEMAP_FACE_NEGATIVE_Y:
                        vecLookAt   = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
                        vecUp       = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
                        break;
                    case D3DCUBEMAP_FACE_POSITIVE_Z:
                        vecLookAt   = D3DXVECTOR3( 0.0f, 0.0f, -1.0f);
                        vecUp       = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);
                        break;
                    case D3DCUBEMAP_FACE_NEGATIVE_Z:
                        vecLookAt   = D3DXVECTOR3(0.0f, 0.0f,1.0f);
                        vecUp       = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
                        break;
                }
    
                D3DXMatrixLookAtLH(&matView, &vecPos, &vecLookAt, &vecUp);
                
                pDevice->SetTransform(D3DTS_VIEW, &matView);
                if (FAILED(hr = m_pRenderToCube->Face((D3DCUBEMAP_FACES)i,0)))
                {
                    OutputDebugString(DXGetErrorString(hr));
                    ::MessageBox(0,"Cannot begin cube map face rendering",0,0);
                }
                
                SpaceXApp::GetInstance()->RenderForCubeMap(pEntry->GameObjectName);
            }
            m_pRenderToCube->End(D3DX_FILTER_LINEAR);
            ++iter;
        }
    RenderForCubeMap() will render all objects except the one specified. This prevents the cube map from reflecting the object that is using the cube map thus causing strange cube map renders.
    The core of this code was extracted from the SDK sample on how to render cube maps. This is code from a container I built that can setup and render cube maps for any object in the system.
    Last edited by VirtualAce; 07-28-2010 at 10:39 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 47
    Last Post: 07-13-2010, 07:22 PM
  2. C Help. square and cube a user inputed number
    By Beedee5889 in forum C Programming
    Replies: 5
    Last Post: 03-11-2010, 01:53 PM
  3. Polynomials and ADT's
    By Emeighty in forum C++ Programming
    Replies: 20
    Last Post: 08-19-2008, 08:32 AM
  4. Creating a map engine.
    By suzakugaiden in forum Game Programming
    Replies: 11
    Last Post: 06-21-2005, 05:06 AM
  5. Searching STL Map Inside STL Map Object :: C++
    By kuphryn in forum C++ Programming
    Replies: 2
    Last Post: 11-14-2002, 09:11 AM