Directx11教程十五之Fog(雾)

首先的本节教程旨在实现雾的特效,程序结构跟SpecularMap那节教程差不多,如下所示:




第一,雾的简介和原理。

雾的实现能帮助游戏实现一种朦朦胧胧的感觉,并且由于视锥体的存在,有些靠近视锥体但是没在视锥体内的物体,进入视锥体后在视觉上有种非常突兀的感觉,如果能在远处附着上一些雾,可减弱物体突然进入视锥体的突兀感。
来看看雾的计算原型模型:


假设雾气因子为FogFactor,E点位摄像机的位置,P点位看到的点的位置,dis(P,E)为相机和看到的点之间的距离。

则存在三种雾模型:

(1)线性雾:线性雾 指的的以眼睛(Camera)和看那到的点之间的距离为计算,雾的强度是随距离的距离变换而呈现线性变换。

线性雾的计算公式

                 FogFactor=(FogEnd-dis(P,E))/(FogEnd-FogStart);
               其中FogEnd=FogStart+FogRange;

(2)指数雾: 线性雾 指的的 以眼睛(Camera)和看那到的点之间的距离为计算,雾的强度是随距离的距离变换而呈现指数变化

指数雾的计算公式

                  FogFator=1.0/2.71828power(dis(P,E)*FogDensity);
                其中FogDensity为雾的密度。

(3)指数平方雾:跟指数雾差不多

指数平方雾的计算公式

     FogFator=1.0/2.71828power((dis(P,E)*FogDensity)*(dis(P,E)*FogDensity));

                           其中FogDensity为雾的密度。


计算出雾气因子(FogFactor)之后,将计算场景颜色,假设场景物体的颜色为SceneColor,最终输出的颜色为color

           color=FogFactor*SceneColor+(1-FogFactor)*FogColor;

            其中FogColor为雾气的颜色


下面看看我的shader代码:
Texture2D ShaderTexture[3];  //纹理资源数组
SamplerState SampleType:register(s0);   //采样方式

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


cbuffer CBLight:register(b1)
{
	float4 SpecularColor;
	float4 AmbientColor;
	float4 DiffuseColor;
	float3 LightDirection;
	float SpecularPow;
};

cbuffer CBCamera:register(b2)
{
	float3 CameraPos;
	float Pad;
};

cbuffer CBFog:register(b3)
{
	float FogStart;
	float FogEnd;
	float pad1;
	float pad2;
};

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


struct VertexOut
{
	float4 Pos:SV_POSITION;
	float3 Pos_W:POSITION;
	float2 Tex:TEXCOORD0;
	float3 Normal_W:NORMAL;
	float3 Tangent_W:TANGENT;
	float3 Binormal_W:BINORMAL;
	float3 LookDirection:NORMAL1;
};


VertexOut VS(VertexIn ina)
{
	VertexOut outa;

	//变换坐标到齐次裁剪空间(CVV)
	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;

	//将法线量由局部空间变换到世界空间,并进行规格化
	outa.Normal_W = mul(ina.Normal, (float3x3)WorldInvTranpose);
	outa.Normal_W = normalize(outa.Normal_W);

	//将切向量由局部空间变换到世界空间,并且进行规格化
	outa.Tangent_W = mul(ina.Tangent,(float3x3)World);
	outa.Tangent_W = normalize(outa.Tangent_W);


	//将切向量由局部空间变换到世界空间,并且进行规格化
	outa.Binormal_W = mul(ina.Binormal, (float3x3)World);
	outa.Binormal_W = normalize(outa.Binormal_W);

	//求出顶点在世界空间的位置
	float3 worldPos= (float3)mul(float4(ina.Pos, 1.0f), World);
	outa.Pos_W = worldPos;

	//计算出每个顶点到相机的单位向量,之后在光栅化阶段进行插值
	outa.LookDirection =CameraPos.xyz - worldPos.xyz;
	outa.LookDirection = normalize(outa.LookDirection);

	return outa;
}


float4 PS(VertexOut outa) : SV_Target
{
	float4 BasePixel; 
	float3 BumpNormal;  //隆起法向量
	float4 color;
	float DiffuseFactor;  //漫反射因子
	float SpecularFactor; //镜面反射因子
	float4 Specular; //镜面反射颜色
	float4 SpecularIntensity; //镜面强度
	float FogFactor;

	//增加漫反射光颜色
	color = AmbientColor;

	//求每个像素的纹理像素颜色
    BasePixel = ShaderTexture[0].Sample(SampleType, outa.Tex);


	//求每个像素的隆起法向量(切线空间)
	BumpNormal=(float3)ShaderTexture[1].Sample(SampleType, outa.Tex);
	BumpNormal = (2.0f*BumpNormal) - 1.0f;


	//-----求出TBN矩阵(已经和世界变换矩阵结合在一起)--------
	float3 N = outa.Normal_W;
	float3 T = outa.Tangent_W;
	float3 B = outa.Binormal_W;
    
	//将隆起法向量由切线空间变换到局部空间,再到世界空间,然后规格化
	//BumpNormal= mul(BumpNormal,float3x3(T,B,N));
	BumpNormal = N + BumpNormal.x*T + BumpNormal.y*B;
	BumpNormal = normalize(BumpNormal);

	//求出漫反射因子
	float3 InvLightDirection = -LightDirection;
	 DiffuseFactor = saturate(dot(BumpNormal, InvLightDirection));
    color += DiffuseColor*DiffuseFactor;
	color = saturate(color);

	//乘以基础纹理颜色
	color = color*BasePixel;

	//如果漫射因子为正时,漫反射光和镜面才存在意义
	if (DiffuseFactor > 0)
	{

		//求出入射光的反射向量,此时的法线量应该为法线贴图的法向量,别把参数位置搞反了
		float3 ReflectLightDir = normalize(reflect(LightDirection,BumpNormal));
		//float3 ReflectLightDir = normalize(2 * DiffuseFactor*BumpNormal - InvLightDirection);
		//求每个像素的镜面强度
		SpecularIntensity = ShaderTexture[2].Sample(SampleType, outa.Tex);

		//求出镜面反射因子
		SpecularFactor = pow(saturate(dot(outa.LookDirection, ReflectLightDir)), SpecularPow);

		//求出镜面颜色,为什么这里用不上SpecularColor??
		Specular = SpecularFactor  *SpecularIntensity;
		color = color + Specular;  //确实只有镜面光被计算 才加上
		
	}
	color = saturate(color);

	//求出相机到像素点的距离
	float EyeToPixelDistance = length(CameraPos - outa.Pos_W);

	//计算出线性雾气因子
	FogFactor = (FogEnd - EyeToPixelDistance) / (FogEnd - FogStart);

	//计算融合雾气后的颜色
	float4 FogColor = float4(0.5f, 0.5f, 0.5f, 1.0f);
	color = FogFactor*color + (1 - FogFactor)*FogColor;
	
	return color;
}


其中背后缓存清除为灰色背景(0.5f,0.5f,0.5f,1.0f);
//第一,清除缓存开始绘制场景,清除背后缓存为灰色,模拟雾的背景
	mD3D->BeginScene(0.5f, 0.5f, 0.5f, 1.0f);

我的程序运行图:



你看距离立方体我们近处部分看的比远处部分要清楚。不过最后得记得清楚背景为灰色,要不输出的效果不够模拟雾天气,
如图:背景颜色为黑色的




最后我的源代码链接如下:


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
不错的dx11入门教程 Tutorial 1: Setting up DirectX 11 with Visual Studio Tutorial 2: Creating a Framework and Window Tutorial 3: Initializing DirectX 11 Tutorial 4: Buffers, Shaders, and HLSL Tutorial 5: Texturing Tutorial 6: Diffuse Lighting Tutorial 7: 3D Model Rendering Tutorial 8: Loading Maya 2011 Models Tutorial 9: Ambient Lighting Tutorial 10: Specular Lighting Tutorial 11: 2D Rendering Tutorial 12: Font Engine Tutorial 13: Direct Input Tutorial 14: Direct Sound Tutorial 15: FPS, CPU Usage, and Timers Tutorial 16: Frustum Culling Tutorial 17: Multitexturing and Texture Arrays Tutorial 18: Light Maps Tutorial 19: Alpha Mapping Tutorial 20: Bump Mapping Tutorial 21: Specular Mapping Tutorial 22: Render to Texture Tutorial 23: Fog Tutorial 24: Clipping Planes Tutorial 25: Texture Translation Tutorial 26: Transparency Tutorial 27: Reflection Tutorial 28: Screen Fades Tutorial 29: Water Tutorial 30: Multiple Point Lights Tutorial 31: 3D Sound Tutorial 32: Glass and Ice Tutorial 33: Fire Tutorial 34: Billboarding Tutorial 35: Depth Buffer Tutorial 36: Blur Tutorial 37: Coming Soon... DirectX 10 Tutorials: Tutorial 1: Setting up DirectX 10 with Visual Studio Tutorial 2: Creating a Framework and Window Tutorial 3: Initializing DirectX 10 Tutorial 4: Buffers, Shaders, and HLSL Tutorial 5: Texturing Tutorial 6: Diffuse Lighting Tutorial 7: 3D Model Rendering Tutorial 8: Loading Maya 2011 Models Tutorial 9: Ambient Lighting Tutorial 10: Specular Lighting Tutorial 11: 2D Rendering Tutorial 12: Font Engine Tutorial 13: Direct Input Tutorial 14: Direct Sound Tutorial 15: FPS, CPU Usage, and Timers Tutorial 16: Frustum Culling Tutorial 17: Multitexturing and Texture Arrays Tutorial 18: Light Maps Tutorial 19: Alpha Mapping Tutorial 20: Bump Mapping Tutorial 21: Specular Mapping Tutorial 22: Render to Texture Tutorial 23: Fog Tutorial 24: Clipping Planes Tutorial 25: Texture Translation Tutorial 26: Transparency Tutorial 27: Reflection Tutorial 28: Screen Fades Tutorial 29: Water Tutorial 30: Multiple Point Lights Tutorial 31: 3D Sound Tutorial 32: Glass and Ice Tutorial 33: Fire Tutorial 34: Billboarding Tutorial 35: Depth Buffer Tutorial 36: Blur Tutorial 37: Coming Soon... DirectX 10 Terrain Tutorials: Tutorial 1: Grid and Camera Movement Tutorial 2: Height Maps Tutorial 3: Terrain Lighting Tutorial 4: Terrain Texturing Tutorial 5: Color Mapped Terrain Tutorial 6: Quad Trees Tutorial 7: Coming Soon... 。。。。。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值