0
$\begingroup$

I'm trying to implement Skybox in DirectX 11 (DirectXTK) but when I'm rendering skybox, then texture is rendered to my sphere model instead of showing skybox outside.

Rendering code:

m_Camera->Render();

m_Camera->GetViewMatrix(viewMatrix);
m_D3D->GetWorldMatrix(worldMatrix);
m_D3D->GetProjectionMatrix(projectionMatrix);

m_D3D->ChangeRasterizerCulling(D3D11_CULL_NONE);
m_D3D->ChangeDepthStencilComparison(D3D11_COMPARISON_LESS_EQUAL);

m_Model->Render(m_D3D->GetDeviceContext());
m_skyboxShader->Render(m_D3D->GetDeviceContext(), m_Model->GetIndexCount(), worldMatrix, viewMatrix, projectionMatrix);

m_D3D->ChangeRasterizerCulling(D3D11_CULL_BACK);
m_D3D->ChangeDepthStencilComparison(D3D11_COMPARISON_LESS);
m_D3D->EndScene();

Skybox.vs

cbuffer MatrixBuffer
{
    matrix worldMatrix;
    matrix viewMatrix;
    matrix projectionMatrix;
};

struct VertexInputType
{
    float4 position : POSITION;    
};

struct PixelInputType
{
    float4 positionSV : SV_POSITION;
    float4 position : POSITION;
};

PixelInputType ColorVertexShader(VertexInputType input)
{
    PixelInputType output;

    input.position.w = 1.0f;
    output.position = input.position;

    output.positionSV = mul(input.position, worldMatrix).xyww;
    output.positionSV = mul(output.positionSV, viewMatrix).xyww;
    output.positionSV = mul(output.positionSV, projectionMatrix).xyww;

    return output;
}

Skybox.ps

TextureCube shaderTexture;
SamplerState SampleType;

struct PixelInputType
{
    float4 positionSV : SV_POSITION;
    float4 position : POSITION;
};

float4 ColorPixelShader(PixelInputType input) : SV_TARGET
{
    return shaderTexture.Sample(SampleType, input.position.xyz);
}

Result DirectX Skybox error

$\endgroup$
0
$\begingroup$

A skybox is a (large) cube that encompasses the entire scene and contains 6 images of a surrounding environment, giving the player the illusion that the environment he's in is actually much larger than it actually is.

In order to do this, you need to draw a Cube (or a Sphere) in your Scene that will represent the Skybox. You then need to sample the Skybox Texture (shaderTexture in your shader) to project it into the geometry. This is exactly what you are doing with your Sphere Model in your Pixel Shader.

The problem you have, is that your Model is too small and your Camera is outside of the Skybox. You need to make the Skybox way bigger, and place your camera inside of it. The best solution is to center the Sky Sphere about the camera in world space, this way when you move the camera around, the Sky follows the camera, giving the illusion that it's infinitely far away and you can't get closer.

PixelInputType ColorVertexShader(VertexInputType input)
{
PixelInputType output;

// Use local vertex position as cubemap lookup vector.
output.position = input.position;

// Transform to world space.
float4 positionWorld = mul(float4(input.position, 1.0f), worldMatrix);

// Always center sky about camera (You need to pass the camera position).
positionWorld.xyz += eyePositionWorld;

// Set z = w so that z/w = 1 (i.e., skydome always on far plane).
output.positionSV = mul(posW, viewProjectionMatrix).xyww;

return output;

}

To keep the Skybox fragments always on the far plane (z component = 1.0) you can set the z component to w. This will turn into 1 after the perspective division is applied. With this little hack you can render the SkySphere after having rendered all your meshes, and they would all be rendered on top of it.

You may also want to do the matrix multiplication on the CPU and pass it in as another parameter for performance reasons.

$\endgroup$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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