简体   繁体   中英

How to create Cubemap in DirectX 9

I'm trying to create a Cube Map in DirectX 9, but for some reason it's not working. I've used DirectX's Texture Utility to create a dds texture file for the cube, but when I draw it, it's only drawing a solid color. Here's the code I've done:

SkyBox.h

#pragma once

#include<D3DX9Mesh.h>
#include"DirectX.h"

class SkyBox{
public:
    SkyBox(LPCSTR textureFile);
    ~SkyBox();

    void Draw();

protected:
    IDirect3DCubeTexture9* texture;
    LPD3DXMESH mesh;
};

SkyBox.cpp

#include"SkyBox.h"

SkyBox::SkyBox(LPCSTR textureFile)
{
    D3DXCreateBox(DirectX::device, 1.0f, 1.0f, 1.0f, &mesh, NULL);
    D3DXCreateCubeTextureFromFile(DirectX::device, textureFile, &texture);
}

SkyBox::~SkyBox()
{
    mesh->Release();
    texture->Release();
}

void SkyBox::Draw()
{
    D3DXHANDLE textureHandle = DirectX::currentShaderEffect->GetParameterByName(0, "tex0");
    DirectX::currentShaderEffect->SetTexture(textureHandle, texture);
    DirectX::currentShaderEffect->CommitChanges();

    UINT passNum = 5;
    DirectX::currentShaderEffect->Begin(&passNum, 0);
    DirectX::currentShaderEffect->BeginPass(5);

    mesh->DrawSubset(0);

    DirectX::currentShaderEffect->EndPass();
    DirectX::currentShaderEffect->End();
}

And this is my shader for the Cube Map:

uniform extern float4x4 mvp;
uniform extern texture tex0;

struct SkyboxVS
{

    float4 pos : POSITION0;
    float3 uv0 : TEXCOORD0;
};

sampler SkyBoxTex = sampler_state
{
    Texture = <tex0>;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU = WRAP;
    AddressV = WRAP;
};

SkyboxVS VertexSkybox(float3 position : POSITION0, float3 texCoord : TEXCOORD0)
{
    SkyboxVS skyVS = (SkyboxVS)0;

    skyVS.pos = mul(float4(position, 1.0f), mvp);
    skyVS.uv0 = texCoord;

    return skyVS;
}

float4 PixelSkybox(float3 texCoord: TEXCOORD0) : COLOR
{
    float4 color = texCUBE(SkyBoxTex, texCoord);

    return color;
}

technique TransformTech
{
    pass P5
    {
        vertexShader = compile vs_2_0 VertexSkybox();
        pixelShader = compile ps_2_0 PixelSkybox();

        ZFunc = Always;
        StencilEnable = true;
        StencilFunc = Always;

        StencilPass = Replace;
        StencilRef = 0;
    }
}

Here's some sample code:

Sky::Sky(const std::string& envmapFilename, float skyRadius)
: mRadius(skyRadius)
{
    HR(D3DXCreateSphere(gd3dDevice, skyRadius, 30, 30, &mSphere, 0));
    HR(D3DXCreateCubeTextureFromFile(gd3dDevice, envmapFilename.c_str(), &mEnvMap));

    ID3DXBuffer* errors = 0;
    HR(D3DXCreateEffectFromFile(gd3dDevice, "sky.fx", 0, 0, 0, 
        0, &mFX, &errors));
    if( errors )
        MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);

    mhTech   = mFX->GetTechniqueByName("SkyTech");
    mhWVP    = mFX->GetParameterByName(0, "gWVP");
    mhEnvMap = mFX->GetParameterByName(0, "gEnvMap");

    // Set effect parameters that do not vary.
    HR(mFX->SetTechnique(mhTech));
    HR(mFX->SetTexture(mhEnvMap, mEnvMap));
}


void Sky::draw()
{
    // Sky always centered about camera's position.
    D3DXMATRIX W;
    D3DXVECTOR3 p = gCamera->pos();
    D3DXMatrixTranslation(&W, p.x, p.y, p.z);
    HR(mFX->SetMatrix(mhWVP, &(W*gCamera->viewProj())));

    UINT numPasses = 0;
    HR(mFX->Begin(&numPasses, 0));
    HR(mFX->BeginPass(0));
    HR(mSphere->DrawSubset(0));
    HR(mFX->EndPass());
    HR(mFX->End());
}

And shader code:

OutputVS EnvMapVS(float3 posL : POSITION0, float3 normalL : NORMAL0, float2 tex0: TEXCOORD0)
{
    // Zero out our output.
    OutputVS outVS = (OutputVS)0;

    // Transform normal to world space.
    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;

    // Transform to homogeneous clip space.
    outVS.posH = mul(float4(posL, 1.0f), gWVP);

    // Pass on texture coordinates to be interpolated in rasterization.
    outVS.tex0 = tex0;

    // 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 = 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.
    return float4(final, gMtrl.diffuse.a*texColor.a);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM