Skyboxes

Skyboxes

一个texture cube常见的一种应用是,把围绕camera的texture cube映射到一个skybox,box或者一个sphere上,并产生一种场景环境的视觉。列表8.1列出了一种skybox effect的代码。
列出8.1 Skybox.fx
/************* Resources *************/

cbuffer CBufferPerObject
{
    float4x4 WorldViewProjection : WORLDVIEWPROJECTION < string UIWidget="None"; >;
}

TextureCube SkyboxTexture <
    string UIName =  "Skybox Texture";
    string ResourceType = "3D";
>;

SamplerState TrilinearSampler
{
    Filter = MIN_MAG_MIP_LINEAR;
};

RasterizerState DisableCulling
{
    CullMode = NONE;
};

/************* Data Structures *************/

struct VS_INPUT
{
    float4 ObjectPosition : POSITION;
};

struct VS_OUTPUT
{
    float4 Position : SV_Position;
    float3 TextureCoordinate : TEXCOORD;
};

/************* Vertex Shader *************/

VS_OUTPUT vertex_shader(VS_INPUT IN)
{
    VS_OUTPUT OUT = (VS_OUTPUT)0;
    
    OUT.Position = mul(IN.ObjectPosition, WorldViewProjection);
    OUT.TextureCoordinate = IN.ObjectPosition;
    
    return OUT;
}

/************* Pixel Shader *************/

float4 pixel_shader(VS_OUTPUT IN) : SV_Target
{
    return SkyboxTexture.Sample(TrilinearSampler, IN.TextureCoordinate);
}

/************* Techniques *************/

technique10 main10
{
    pass p0
    {
        SetVertexShader(CompileShader(vs_4_0, vertex_shader()));
        SetGeometryShader(NULL);
        SetPixelShader(CompileShader(ps_4_0, pixel_shader()));
            
        SetRasterizerState(DisableCulling);
    }
}


Skybox Preamble

Skybox effect的代码相比上一章的effects代码要简单的多。CBufferPerFrame模块被全部去掉了,CBufferPerObject部分只包含一个WorldViewProjection矩阵;用于计算specular highlight的成员全部删除了。
输出纹理命名为SkyboxTexture,并使用TextureCube类型而不是Texture2D。另外,SampleState对象被修改为Trilinear-Sampler,并去掉了addressing mode的显式设定。Minification,magnification和mip-level三种采样的线性插值组合被称为trilinear sampling(三重采样)(该名称来源于bilinear interpolation双重采样,在一个mipmap的纹理元素之间进行双向插值,再在两个mip-levels之间进行插值,所以叫三重采样)。对于cube maps,不需要设置addressing mode。
现在,VS_INPUT结构体中只包含一个vertex position成员。由于不用执行光照计算,也就不需要表面的法向量,texture coordinates直接在vertex shader中确定。同样地,VS_OUTPUT结构体只包含了homogenous clip space中的坐标位置,以及用于传递cube map纹理坐标的成员TextureCoordinate。

Skybox Vertex and Pixel Shader

与之前一样,vertex shader首先把vertex position变换到homogeneous space中。然后把object position赋值给texture coordinates。乍看之下,可能觉得很奇怪,因为一个cube map是通过一个方向向量进行sample,而不是一个position。但是回顾一下第二章,“A 3D/Math Primer”所讨论的,一个position可以看成是起点位于坐标系原点的方向向量。
在pixel shader代码中,只是对texture cube进行sample,并把sample结果作为最终的输出颜色。

Skybox Output

图8.5显示了在NVIDIA FX Composer中把skybox effect指定到一个sphere上的输出结果。在该图中,camera位于sphere里面,并显示了一个参考表格。由于一个skybox是环绕着camera,必须禁用backface culling,如8.1列表的代码所示。同时还要把sphere缩放到一个合适的大小。
Skyboxes_第1张图片
图8.5 Skybox.fx looking outward from inside the associated sphere. (Texture by Emil
Persson.)

注意
如果在自己缩写的CPU应用程序中使用这个effect,必须保证skybox的坐标总是与camera连在一起。这种情况下,观察永远无法达到world space的边缘,也就不会破坏被一种环境所包围的视觉。

你可能感兴趣的:(Skyboxes)