3
\$\begingroup\$

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.

- IGNORE FOLLOWING AND SKIP DOWN TO UPDATE -

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.

IMAGE REMOVED

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 WVP;
    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;

XMMATRIX WVP;
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->RSSetState(rs);
dc->DrawIndexed(faces * 3, 0, 0);

return;

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(
    device,
    pathToTexture,
    0,
    D3D11_USAGE_DEFAULT,
    D3D11_BIND_SHADER_RESOURCE,
    0,
    D3D11_RESOURCE_MISC_TEXTURECUBE,  // I'm guessing this is wrong/no effect.
    false,
    (ID3D11Resource**)&texture,
    &shaderResView,
    nullptr);

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.

\$\endgroup\$
1
\$\begingroup\$

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.

D3DX11_IMAGE_LOAD_INFO loadSMInfo;
loadSMInfo.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;

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

D3D11_TEXTURE2D_DESC SMTextureDesc;
SMTexture->GetDesc(&SMTextureDesc);

D3D11_SHADER_RESOURCE_VIEW_DESC SMViewDesc;
SMViewDesc.Format = SMTextureDesc.Format;
SMViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
SMViewDesc.TextureCube.MipLevels = SMTextureDesc.MipLevels;
SMViewDesc.TextureCube.MostDetailedMip = 0;

hr = d3d11Device->CreateShaderResourceView(SMTexture, &SMViewDesc, &smrv);
\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
  • \$\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 '16 at 14:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.