Directx11教程十五之Fog(雾)
2016-10-13 16:01
369 查看
首先的本节教程旨在实现雾的特效,程序结构跟SpecularMap那节教程差不多,如下所示:
来看看雾的计算原型模型:
假设雾气因子为FogFactor,E点位摄像机的位置,P点位看到的点的位置,dis(P,E)为相机和看到的点之间的距离。
则存在三种雾模型:
(1)线性雾:线性雾指的的以眼睛(Camera)和看那到的点之间的距离为计算,雾的强度是随距离的距离变换而呈现线性变换。
其中FogEnd=FogStart+FogRange;
(2)指数雾:线性雾指的的以眼睛(Camera)和看那到的点之间的距离为计算,雾的强度是随距离的距离变换而呈现指数变化
其中FogDensity为雾的密度。
(3)指数平方雾:跟指数雾差不多
其中FogDensity为雾的密度。
计算出雾气因子(FogFactor)之后,将计算场景颜色,假设场景物体的颜色为SceneColor,最终输出的颜色为color
color=FogFactor*SceneColor+(1-FogFactor)*FogColor;
其中FogColor为雾气的颜色
下面看看我的shader代码:
其中背后缓存清除为灰色背景(0.5f,0.5f,0.5f,1.0f);
我的程序运行图:
你看距离立方体我们近处部分看的比远处部分要清楚。不过最后得记得清楚背景为灰色,要不输出的效果不够模拟雾天气,
如图:背景颜色为黑色的
最后我的源代码链接如下:
点击打开链接
第一,雾的简介和原理。
雾的实现能帮助游戏实现一种朦朦胧胧的感觉,并且由于视锥体的存在,有些靠近视锥体但是没在视锥体内的物体,进入视锥体后在视觉上有种非常突兀的感觉,如果能在远处附着上一些雾,可减弱物体突然进入视锥体的突兀感。来看看雾的计算原型模型:
假设雾气因子为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);
我的程序运行图:
如图:背景颜色为黑色的
最后我的源代码链接如下:
点击打开链接
相关文章推荐
- Java NIO框架Netty教程(十五)-利用Netty进行文件传输
- PADS Logic图文教程(十五):改变元件(Part)的值
- Directx11教程(56) 建立一个skydome
- Directx11教程(15) D3D11管线(4)
- WPF入门教程系列十五——WPF中的数据绑定(一)
- 【D3.js数据可视化系列教程】--(十五)SVG基本图形绘制
- Directx11教程(31) 纹理映射(1)
- Directx11教程十三之SpecularMap(高光贴图)
- Scott Mitchell 的ASP.NET 2.0数据教程之十五:在GridView的页脚中显示统计信息
- Directx11教程十六之ClipPlane(裁剪面)
- Directx11教程三十八之Pick(拾取技术)
- Directx11教程(43) 纹理映射(13)-动态纹理映射
- 黑客编程教程(十五)HTTP代理
- Scott Mitchell 的ASP.NET 2.0数据教程之十五:在GridView的页脚中显示统计信息
- jQuery学习教程十五: jQuery - 获取并设置 CSS 类
- Spring.NET教程(十五)——事务传播行为(基础篇)
- PostgreSQL教程(十五):系统表详解
- Android高手进阶教程(十五)之---通过Location获取Address的使用!
- Directx11教程(55) 建立球形和锥形物体
- OpenGL ES 学习教程(十五) 从 颜色缓冲区(FBO的颜色附着)中 读取颜色数据 保存到图片(FreeImage)