您的位置:首页 > 其它

D3D11地形渲染教程十三之PerturbedCloud(翻滚的云,或者扰乱云的形状)

2017-01-26 13:07 483 查看
上一节教程D3D11地形渲染教程十一之SkyDome(天空盒)我们实现了“会移动的云层”,但是上节教程的云是不具备翻滚效果的,真实世界的云应该有翻滚的效果,程序的结构如下:



一,PerturbedCloud(翻滚的云)

PerturbedCloud(翻滚的云)的实现,可以参考教程D3D11教程二十三之Fire(摇动的火),我们再一次借用NoiseTexture(噪声纹理)来模拟云层翻滚的自然现象。其实,我觉得,由于纹理描述的对象的形状的些许改变,都能用NoiseTexture来模拟这种改变。比如火焰纹理的火焰的摇动效果,又如云层纹理的云朵的翻滚效果。

这节教程的代码跟上节教程差不多,主要是Shader着色代码不一样和用的纹理不一样,上一节教程我们使用了两张云层纹理,这一节教程我们使用一张云层纹理和噪声纹理。

云层纹理如下:



噪声纹理(NoiseTexture)如下:(注意噪声纹理为灰度图,纹理上像素颜色的R值,G值,B值是相等的,是随机的量,能模拟自然现象的某些量)



二,Shader代码实现

Shader代码实现:

(1)云层纹理往XY方向移动,并且进行翻滚

Texture2D CloudTexture1:register(t0);  //纹理资源
Texture2D NoiseTexture:register(t1);  //纹理资源
SamplerState SampleType:register(s0);   //采样方式

//VertexShader
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
};

cbuffer CBSkyCloudPlane:register(b1)
{
float Translation;
float brightness;
float PerturbScale;
float pad;
};

struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0;  //多重纹理可以用其它数字
};

struct VertexOut
{
float4 Pos:SV_POSITION;
float2 Tex:TEXCOORD0;
};

VertexOut VS(VertexIn ina)
{
VertexOut outa;
outa.Pos = mul(float4(ina.Pos,1.0f), World);
outa.Pos = mul(outa.Pos, View);
outa.Pos = mul(outa.Pos, Proj);
outa.Tex= ina.Tex;
return outa;
}

float4 PS(VertexOut outa) : SV_Target
{
float4 color;
float2 Tex;
float4 Perturb;
float4 TexColor;

//计算移动后的纹理坐标
Tex.x = outa.Tex.x + Translation;
Tex.y = outa.Tex.y;

//利用移动后的纹理坐标对噪声纹理进行采样
Perturb= NoiseTexture.Sample(SampleType, Tex);

//利用PerturbScale对Perturb(扰乱)值进行缩放
Perturb = Perturb*PerturbScale;

//利用Perturb值(扰乱值)对纹理采样坐标进行扰乱,以便制作翻滚云的效果
Tex.xy = outa.Tex.xy + Perturb.xy+ Translation;

//使用扰乱后的纹理坐标对云彩纹理进行采样
TexColor = CloudTexture1.Sample(SampleType, Tex);

//用brightness调节颜色的亮度
color = brightness*TexColor;

return color;
}


程序运行结果:(这不是Gif,看不到云翻滚的动态效果,望见谅)



解释云翻滚的原因:假设在SkyPlane某一部分存在三个点A(0.6,0.6),B(0.5,0.5),C(0.4,0.4),又假设纹理纹理坐标移动速度(Speed)是0.1,在第一帧中Translation为0.1,则A像素对噪声纹理采样的坐标为(0.7,0.6),而B像素对噪声纹理采样的坐标为(0.6,0.5),,C像素对噪声纹理采样的坐标为(0.5,0.4),并且A的基础纹理坐标(outa.Tex.xy+Translation)变为(0.7,0.7),B的基础纹理坐标(outa.Tex.xy+Translation)变为(0.6,0.6),C的基础纹理坐标(outa.Tex.xy+Translation)变为(0.5,0.5);
    在第二帧画面中,Translation变为0.2,则A像素对噪声纹理采样的坐标为(0.8,0.6),而B像素对噪声纹理采样的坐标为(0.7,0.5),,C像素对噪声纹理采样的坐标为(0.6,0.4),并且A的基础纹理坐标(outa.Tex.xy+Translation)变为(0.8,0.8),B的基础纹理坐标(outa.Tex.xy+Translation)变为(0.7,0.7),C的基础纹理坐标(outa.Tex.xy+Translation)变为(0.6,0.6);。
这里我分析出:第一帧画面中,A像素的基础纹理坐标(outa.Tex.xy+Translation)为(0.7,0.7),而A像素对噪声纹理采样的坐标为(0.7,0.6)在第二张画面中,B像素基础纹理坐标(outa.Tex.xy+Translation)变为(0.7,0.7),而B像素对噪声纹理采样的坐标为(0.7,0.5)。一样的基础纹理坐标确有不同的噪声纹理采样坐标,获取的云层干扰量(噪声量)不一样,这样云层形态就无法维持稳定,也就是云层翻滚的本质所在。


当我把上面的代码改为下面的,云层就成了不会翻滚的.

(2)云层纹理往XY方向移动,不进行翻滚

Texture2D CloudTexture1:register(t0);  //纹理资源
Texture2D NoiseTexture:register(t1);  //纹理资源
SamplerState SampleType:register(s0);   //采样方式

//VertexShader
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
};

cbuffer CBSkyCloudPlane:register(b1)
{
float Translation;
float brightness;
float PerturbScale;
float pad;
};

struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0;  //多重纹理可以用其它数字
};

struct VertexOut
{
float4 Pos:SV_POSITION;
float2 Tex:TEXCOORD0;
};

VertexOut VS(VertexIn ina)
{
VertexOut outa;
outa.Pos = mul(float4(ina.Pos,1.0f), World);
outa.Pos = mul(outa.Pos, View);
outa.Pos = mul(outa.Pos, Proj);
outa.Tex= ina.Tex;
return outa;
}

float4 PS(VertexOut outa) : SV_Target
{
float4 color;
float2 Tex;
float4 Perturb;
float4 TexColor;

//计算移动后的纹理坐标
Tex.x = outa.Tex.x + Translation;
Tex.y = outa.Tex.y + Translation;

//利用移动后的纹理坐标对噪声纹理进行采样
Perturb= NoiseTexture.Sample(SampleType, Tex);

//利用PerturbScale对Perturb(扰乱)值进行缩放
Perturb = Perturb*PerturbScale;

//利用Perturb值(扰乱值)对纹理采样坐标进行扰乱,以便制作翻滚云的效果
Tex.xy = outa.Tex.xy + Perturb.xy+ Translation;

//使用扰乱后的纹理坐标对云彩纹理进行采样
TexColor = CloudTexture1.Sample(SampleType, Tex);

//用brightness调节颜色的亮度
color = brightness*TexColor;

return color;
}


解释云不翻滚的原因:假设在SkyPlane某一部分存在三个点A(0.6,0.6),B(0.5,0.5),C(0.4,0.4),又假设纹理纹理坐标移动速度(Speed)是0.1,在第一帧中Translation为0.1,则A像素对噪声纹理采样的坐标为(0.7,0.7),而B像素对噪声纹理采样的坐标为(0.6,0.6),,C像素对噪声纹理采样的坐标为(0.5,0.5),并且A的基础纹理坐标(outa.Tex.xy+Translation)变为(0.7,0.7),B的基础纹理坐标(outa.Tex.xy+Translation)变为(0.6,0.6),C的基础纹理坐标(outa.Tex.xy+Translation)变为(0.5,0.5);
    在第二帧画面中,Translation变为0.2,则A像素对噪声纹理采样的坐标为(0.8,0.8),而B像素对噪声纹理采样的坐标为(0.7,0.7),,C像素对噪声纹理采样的坐标为(0.6,0.6),并且A的基础纹理坐标(outa.Tex.xy+Translation)变为(0.8,0.8),B的基础纹理坐标(outa.Tex.xy+Translation)变为(0.7,0.7),C的基础纹理坐标(outa.Tex.xy+Translation)变为(0.6,0.6);。
这里我分析出:第一帧画面中,A像素的基础纹理坐标(outa.Tex.xy+Translation)为(0.7,0.7),而A像素对噪声纹理采样的坐标为(0.7,0.7)在第二张画面中,B像素基础纹理坐标(outa.Tex.xy+Translation)变为(0.7,0.7),而B像素对噪声纹理采样的坐标为(0.7,0.7)。一样的基础纹理坐标确有相同的噪声纹理采样坐标,获取的云层干扰量(噪声量)一样,这样云层形态就维持稳定,也就是云层不翻滚的本质所在。

(3)云层纹理往XY方向移动,并且进行翻滚

Texture2D CloudTexture1:register(t0);  //纹理资源
Texture2D NoiseTexture:register(t1);  //纹理资源
SamplerState SampleType:register(s0);   //采样方式

//VertexShader
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
};

cbuffer CBSkyCloudPlane:register(b1)
{
float Translation;
float brightness;
float PerturbScale;
float pad;
};

struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0;  //多重纹理可以用其它数字
};

struct VertexOut
{
float4 Pos:SV_POSITION;
float2 Tex:TEXCOORD0;
};

VertexOut VS(VertexIn ina)
{
VertexOut outa;
outa.Pos = mul(float4(ina.Pos,1.0f), World);
outa.Pos = mul(outa.Pos, View);
outa.Pos = mul(outa.Pos, Proj);
outa.Tex= ina.Tex;
return outa;
}

float4 PS(VertexOut outa) : SV_Target
{
float4 color;
float2 Tex;
float4 Perturb;
float4 TexColor;

//计算移动后的纹理坐标
Tex.x = outa.Tex.x ;
Tex.y = outa.Tex.y + Translation;

//利用移动后的纹理坐标对噪声纹理进行采样
Perturb= NoiseTexture.Sample(SampleType, Tex);

//利用PerturbScale对Perturb(扰乱)值进行缩放
Perturb = Perturb*PerturbScale;

//利用Perturb值(扰乱值)对纹理采样坐标进行扰乱,以便制作翻滚云的效果
Tex.xy = outa.Tex.xy + Perturb.xy+ Translation;

//使用扰乱后的纹理坐标对云彩纹理进行采样
TexColor = CloudTexture1.Sample(SampleType, Tex);

//用brightness调节颜色的亮度
color = brightness*TexColor;

return color;
}


(4)云层纹理不移动,但进行翻滚

Texture2D CloudTexture1:register(t0);  //纹理资源
Texture2D NoiseTexture:register(t1);  //纹理资源
SamplerState SampleType:register(s0);   //采样方式

//VertexShader
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
};

cbuffer CBSkyCloudPlane:register(b1)
{
float Translation;
float brightness;
float PerturbScale;
float pad;
};

struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0;  //多重纹理可以用其它数字
};

struct VertexOut
{
float4 Pos:SV_POSITION;
float2 Tex:TEXCOORD0;
};

VertexOut VS(VertexIn ina)
{
VertexOut outa;
outa.Pos = mul(float4(ina.Pos,1.0f), World);
outa.Pos = mul(outa.Pos, View);
outa.Pos = mul(outa.Pos, Proj);
outa.Tex= ina.Tex;
return outa;
}

float4 PS(VertexOut outa) : SV_Target
{
float4 color;
float2 Tex;
float4 Perturb;
float4 TexColor;

//计算移动后的纹理坐标
Tex.x = outa.Tex.x ;
Tex.y = outa.Tex.y + Translation;

//利用移动后的纹理坐标对噪声纹理进行采样
Perturb= NoiseTexture.Sample(SampleType, Tex);

//利用PerturbScale对Perturb(扰乱)值进行缩放
Perturb = Perturb*PerturbScale;

//利用Perturb值(扰乱值)对纹理采样坐标进行扰乱,以便制作翻滚云的效果
Tex.xy = outa.Tex.xy + Perturb.xy;

//使用扰乱后的纹理坐标对云彩纹理进行采样
TexColor = CloudTexture1.Sample(SampleType, Tex);

//用brightness调节颜色的亮度
color = brightness*TexColor;

return color;
}


(5)云层纹理往Y方向移动,但不进行翻滚

Texture2D CloudTexture1:register(t0);  //纹理资源
Texture2D NoiseTexture:register(t1);  //纹理资源
SamplerState SampleType:register(s0);   //采样方式

//VertexShader
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
};

cbuffer CBSkyCloudPlane:register(b1)
{
float Translation;
float brightness;
float PerturbScale;
float pad;
};

struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0;  //多重纹理可以用其它数字
};

struct VertexOut
{
float4 Pos:SV_POSITION;
float2 Tex:TEXCOORD0;
};

VertexOut VS(VertexIn ina)
{
VertexOut outa;
outa.Pos = mul(float4(ina.Pos,1.0f), World);
outa.Pos = mul(outa.Pos, View);
outa.Pos = mul(outa.Pos, Proj);
outa.Tex= ina.Tex;
return outa;
}

float4 PS(VertexOut outa) : SV_Target
{
float4 color;
float2 Tex;
float4 Perturb;
float4 TexColor;

//计算移动后的纹理坐标
Tex.x = outa.Tex.x ;
Tex.y = outa.Tex.y + Translation;

//利用移动后的纹理坐标对噪声纹理进行采样
Perturb= NoiseTexture.Sample(SampleType, Tex);

//利用PerturbScale对Perturb(扰乱)值进行缩放
Perturb = Perturb*PerturbScale;

//利用Perturb值(扰乱值)对纹理采样坐标进行扰乱,以便制作翻滚云的效果
Tex.xy = Tex.xy + Perturb.xy;

//使用扰乱后的纹理坐标对云彩纹理进行采样
TexColor = CloudTexture1.Sample(SampleType, Tex);

//用brightness调节颜色的亮度
color = brightness*TexColor;

return color;
}


(6)云层纹理往X方向移动,并且进行翻滚

Texture2D CloudTexture1:register(t0);  //纹理资源
Texture2D NoiseTexture:register(t1);  //纹理资源
SamplerState SampleType:register(s0);   //采样方式

//VertexShader
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
};

cbuffer CBSkyCloudPlane:register(b1)
{
float Translation;
float brightness;
float PerturbScale;
float pad;
};

struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0;  //多重纹理可以用其它数字
};

struct VertexOut
{
float4 Pos:SV_POSITION;
float2 Tex:TEXCOORD0;
};

VertexOut VS(VertexIn ina)
{
VertexOut outa;
outa.Pos = mul(float4(ina.Pos,1.0f), World);
outa.Pos = mul(outa.Pos, View);
outa.Pos = mul(outa.Pos, Proj);
outa.Tex= ina.Tex;
return outa;
}

float4 PS(VertexOut outa) : SV_Target
{
float4 color;
float2 Tex;
float4 Perturb;
float4 TexColor;

//计算移动后的纹理坐标
Tex.x = outa.Tex.x ;
Tex.y = outa.Tex.y + Translation;

//利用移动后的纹理坐标对噪声纹理进行采样
Perturb= NoiseTexture.Sample(SampleType, Tex);

//利用PerturbScale对Perturb(扰乱)值进行缩放
Perturb = Perturb*PerturbScale;

//利用Perturb值(扰乱值)对纹理采样坐标进行扰乱,以便制作翻滚云的效果
outa.Tex.x = outa.Tex.x + Translation;
Tex.xy = outa.Tex.xy + Perturb.xy;

//使用扰乱后的纹理坐标对云彩纹理进行采样
TexColor = CloudTexture1.Sample(SampleType, Tex);

//用brightness调节颜色的亮度
color = brightness*TexColor;

return color;
}


以上都可以用我对(1)和(2)的分析方法分析出原因来。
另外注意一下,PerturbScale值的大小控制了干扰云层量的大小,也就是云翻滚的激烈程序。PerturbScale值大,则云翻滚激烈。反之,不激烈.

源代码的链接如下:
http://download.csdn.net/detail/qq_29523119/9744846
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: