So I have been spending a lot of time recently implementing a working skybox/skysphere, and have almost completed it. The last thing that I need to do is to load my given texture, a skybox texture consisting of 6 equal images, as a cube map and not a normal texture like I have been doing.


As you can see from the following image, the skybox texture is being loaded as a normal 2D texture and therefore gets warped by my HLSL effect as it should be. I also noticed that when I enable my vertex buffer, I get no visual output except for the default clear color (light blue). The picture taken below is rendered without my vertex buffer activated, and only my index buffer working. Also notable that this texture is being applied to a sphere currently, but I plan to move to a box once I get this working.


I load the sky texture in with the following function.

ID3D11Texture2D* texture;
ID3D11ShaderResourceView* shaderResView;

// ...

CreateDDSTextureFromFileEx(device, pathToTexture, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, D3D11_RESOURCE_MISC_TEXTURECUBE, false, (ID3D11Resource**)&texture, &shaderResView, nullptr);

My skybox render function is below. I also added some header code if you are curious.

// In header file //

struct Vertex
    Vertex() {}
    Vertex(float x, float y, float z,
        float u, float v,
        float nx, float ny, float nz)
        : pos(x, y, z), tex(u, v), nor(nx, ny, nz) {}

    XMFLOAT3 pos;
    XMFLOAT2 tex;
    XMFLOAT3 nor;

struct SKY
    XMMATRIX World;

// In header file //

XMMATRIX scale, trans;
sky = XMMatrixIdentity();

// 'cpos' is the camera position vector.
scale = XMMatrixScaling(2.0, 2.0, 2.0);
trans = XMMatrixTranslation(XMVectorGetX(cpos), XMVectorGetY(cpos), XMVectorGetZ(cpos));
sky = scale * trans;

UINT s = sizeof(Vertex);
UINT o = 0;

dc->IASetIndexBuffer(sib, DXGI_FORMAT_R32_UINT, 0);
//dc->IASetVertexBuffers(0, 1, &svb, &s, &o);

// NOTICE: The vertex buffer is commented out here, which
// produces the effect as seen in the screenshot of this
// post. When rendering without commenting it out, the only
// display output is of the background color.

WVP = sky * view * proj;
SKYOBJ.WVP = XMMatrixTranspose(WVP);
SKYOBJ.World = XMMatrixTranspose(sky);
dc->UpdateSubresource(SKYOBJBUFFER, 0, NULL, &SKYOBJ, 0, 0);
dc->VSSetConstantBuffers(0, 1, &SKYOBJBUFFER);
dc->PSSetShaderResources(0, 1, &srv);
dc->PSSetSamplers(0, 1, &ss);

dc->VSSetShader(vs, 0, 0);
dc->PSSetShader(ps, 0, 0);
dc->OMSetDepthStencilState(dss, 0);
dc->DrawIndexed(faces * 3, 0, 0);


UPDATE: So after quite a bit of playing around, I managed to pull off a working skysphere with almost a working texture. The following pictures are of the current result. New Result 1New Result 2

From the above images, you can clearly see that I produced a working sphere/box, and all that is left to do is load the texture in as a texture cube, not a plain texture. The following is my current texture loading function, which I thought would do the job. (Obviously doesn't).

ID3D11Texture2D* texture;
ID3D11ShaderResourceView* shaderResView;

// ...

hr = CreateDDSTextureFromFileEx(
    D3D11_RESOURCE_MISC_TEXTURECUBE,  // I'm guessing this is wrong/no effect.

And here is my vertex and pixel shader for the skybox itself. (Put here in case I am missing something crucial.)

SamplerState ss;
TextureCube skyMap;

cbuffer SKY
    float4x4 WVP;
    float4x4 World;

struct vIn
    float3 pos : POSITION;

struct pIn
    float4 pos : SV_POSITION;
    float3 tex : TEXCOORD;

pIn vmain(vIn i)
    pIn o = (pIn)0;

    o.pos = mul(float4(i.pos, 1.0f), WVP).xyww;  // Disable Z
    o.tex = i.pos;

    return o;

float4 pmain(pIn i) : SV_TARGET
    return skyMap.Sample(ss, i.tex);

Thank you in advance.


2 Answers 2


A Cube Map is actually an array of six 2D textures, two for each axis (x, -x, y, -y, z, -z). The first thing we do when loading a cube map is tell D3D we will be loading a texture cube, by creating a D3DX11_IMAGE_LOAD_INFO structure and setting its MiscFlags member with D3D11_RESOURCE_MISC_TEXTURECUBE.

Then we will create a 2D texture from the file. This 2D texture will actually be an array now since we said we are loading a texture cube.

Next we get the description of our texture so we can create a resource view description that matches the texture we loaded in.

Now we will create the shader resource view description. We will say that this resource view is a texture cube, or an array of 2D textures, so when the pixel shader is texturing a pixel, it will know how to use the 3D coordinates we give it, which are used to find the texel on the texture cube. Remember a 2D texture uses (u, v) coordinates, well a 3D texture uses (u, v, w) coordinates.

And finally we create the resource view using the texture we loaded in from a file, the shader resource views description, and storing the shader resource view in smrv.


ID3D11Texture2D* SMTexture = 0;
hr = D3DX11CreateTextureFromFile(d3d11Device, L"skymap.dds", 
    &loadSMInfo, 0, (ID3D11Resource**)&SMTexture, 0);


SMViewDesc.Format = SMTextureDesc.Format;
SMViewDesc.TextureCube.MipLevels = SMTextureDesc.MipLevels;
SMViewDesc.TextureCube.MostDetailedMip = 0;

hr = d3d11Device->CreateShaderResourceView(SMTexture, &SMViewDesc, &smrv);

You don't render a skybox as a "cubemap". You often render objects using a environment cubemap that matches the skybox, but the skybox itself is just rendered with a set of 2D textures.

On Direct3D Feature Level 10.0 or later hardware, you can use a Texture2D array with 6 faces as both a cubemap and with another shader as six individual faces.

The WIC loader only loads 2D textures. If you want to pre-create complex surfaces like 2D arrays, cubemaps, or volume maps you should use DDS files instead. The texassemble and texconv tools can help with that.

  • \$\begingroup\$ Ok, so I realized that WIC will not work and moved on to DDS Texture Loader, with a new loading function that looks like this: CreateDDSTextureFromFileEx(d, sky, 0, D3D11_USAGE_DEFAULT, D3D11_BIND_SHADER_RESOURCE, 0, D3D11_RESOURCE_MISC_TEXTURECUBE, false, (ID3D11Resource**)&skytex, &srv, nullptr); Am I missing anything here? I still have the exact same result. \$\endgroup\$
    – Xenonic
    Apr 21, 2016 at 14:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .