- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章C#使用Shader实现夜幕降临倒计时的效果由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
最近火爆全球的pc游戏battlerite(战争仪式)在倒计时的会生成一种类似夜幕降临的效果,会以战场中心为圆心,某个长度为半径的范围外是暗的,而这个半径会逐渐缩小,而圆之外的阴暗部分是附着地形的,本文就尝试使用屏幕后处理的手段来实现这种效果.
(暂时缺少battlerite的截图,稍后会补上) 。
首先看效果图:
注:本文参考了tasharen fog of war插件 。
创建一个c#脚本,命名为nightfall.cs,为nightfall类创建一些公共变量(nightcolor,center和radius),另外还需要一个nightfall.shader.
首先,我们要确定这个效果是在场景渲染之后还未送到屏幕显示之前的实现的,所以,nightfall脚本是要挂载到主camera上的(添加特性[requirecomponent(typeof(camera))]),并要实现onrenderimage方法.
其次,在onrenderimage方法里,我们最终需要调用graphics.blit方法,而这个方法的第三个参数是material类型,所以我们需要在代码里创建一个临时材质,这个材质使用了nightfall.shader.
再次,我们需要在shader里面将屏幕坐标转换为世界坐标,来计算与世界中心的坐标,所以我们需要mvp的逆矩阵(参考shader山下(十六)坐标空间与转换矩阵).
最后,为了附着地形,我们需要在shader计算深度,也就是坐标点与摄像机的相对距离,所以需要摄像机的位置.
c#的代码:
using unityengine,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
[requirecomponent(
typeof
(camera))]
public
class
nightfall : monobehaviour
{
public
shader shader;
public
color nightcolor =
new
color(0.05f, 0.05f, 0.05f, 0.5f);
public
vector3 center = vector3.zero;
public
float
radius = 10;
camera mcam;
matrix4x4 minversemvp;
material mmat;
/// the camera we're working with needs depth.
void
onenable ()
{
mcam = getcomponent<camera>();
mcam.depthtexturemode = depthtexturemode.depth;
if
(shader ==
null
) shader = shader.find(
"image effects/nightfall"
);
}
/// destroy the material when disabled.
void
ondisable () {
if
(mmat) destroyimmediate(mmat); }
/// automatically disable the effect if the shaders don't support it.
void
start ()
{
if
(!systeminfo.supportsimageeffects || !shader || !shader.issupported)
{
enabled =
false
;
}
}
// called by camera to apply image effect
void
onrenderimage (rendertexture source, rendertexture destination)
{
print (nightcolor);
print (destination);
// calculate the inverse modelview-projection matrix to convert screen coordinates to world coordinates
minversemvp = (mcam.projectionmatrix * mcam.worldtocameramatrix).inverse;
if
(mmat ==
null
)
{
mmat =
new
material(shader);
mmat.hideflags = hideflags.hideanddontsave;
}
vector4 campos = mcam.transform.position;
// this accounts for anti-aliasing on windows flipping the depth uv coordinates.
// despite the official documentation, the following approach simply doesn't work:
// http://docs.unity3d.com/documentation/components/sl-platformdifferences.html
if
(qualitysettings.antialiasing > 0)
{
runtimeplatform pl = application.platform;
if
(pl == runtimeplatform.windowseditor ||
pl == runtimeplatform.windowsplayer ||
pl == runtimeplatform.windowswebplayer)
{
campos.w = 1f;
}
}
mmat.setvector(
"_campos"
, campos);
mmat.setmatrix(
"_inversemvp"
, minversemvp);
mmat.setcolor(
"_nightcolor"
, nightcolor);
mmat.setvector (
"_center"
, center);
mmat.setfloat (
"_radius"
, radius);
graphics.blit(source, destination, mmat);
}
}
|
shader代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
shader
"image effects/nightfall"
{
properties
{
_nightcolor (
"night color"
, color) = (0.05, 0.05, 0.05, 0.05)
_center (
"center"
, vector) = (0,0,0,0)
_radius (
"radius"
,
float
) = 10
}
subshader
{
pass
{
ztest always
cull off
zwrite off
fog { mode off }
blend srcalpha oneminussrcalpha
cgprogram
#pragma vertex vert_img
#pragma fragment frag vertex:vert
#pragma fragmentoption arb_precision_hint_fastest
#include "unitycg.cginc"
sampler2d _cameradepthtexture;
uniform float4x4 _inversemvp;
uniform float4 _campos;
uniform half4 _nightcolor;
uniform half4 _center;
uniform half _radius;
struct
input
{
float4 position : position;
float2 uv : texcoord0;
};
void
vert (inout appdata_full v,
out
input o)
{
o.position = mul(unity_matrix_mvp, v.vertex);
o.uv = v.texcoord.xy;
}
float3 camtoworld (
in
float2 uv,
in
float
depth)
{
float4 pos = float4(uv.x, uv.y, depth, 1.0);
pos.xyz = pos.xyz * 2.0 - 1.0;
pos = mul(_inversemvp, pos);
return
pos.xyz / pos.w;
}
fixed4 frag (input i) : color
{
#if shader_api_d3d9 || shader_api_d3d11
float2 depthuv = i.uv;
depthuv.y = lerp(depthuv.y, 1.0 - depthuv.y, _campos.w);
float
depth = unity_sample_depth(tex2d(_cameradepthtexture, depthuv));
float3 pos = camtoworld(depthuv, depth);
#else
float
depth = unity_sample_depth(tex2d(_cameradepthtexture, i.uv));
float3 pos = camtoworld(i.uv, depth);
#endif
// limit to sea level
if
(pos.y < 0.0)
{
// this is a simplified version of the ray-plane intersection formula: t = -( n.o + d ) / ( n.d )
float3 dir = normalize(pos - _campos.xyz);
pos = _campos.xyz - dir * (_campos.y / dir.y);
}
half4 col;
float
dis = length(pos.xz - _center.xz);
if
(dis < _radius)
{
col = fixed4(0,0,0,0);
}
else
{
col = _nightcolor;
}
return
col;
}
endcg
}
}
fallback off
}
|
需要说明的几个点:
1、因为平台差异性,为了兼容direct3d,所以在c#和shader里通过campos(_campos)的w分量来调整uv坐标.
2、这里虽然没有声明_maintex,但是_maintex实际上就是即将成像的屏幕图像,所以这里的i.uv也就是指屏幕图像的纹理坐标.
3、_cameradepthtexture是摄像机的深度纹理,通过unity_sample_depth方法获取深度.
4、camtoworld里面,先是根据uv坐标和深度depth创建了一个float4的坐标值pos,然后对pos乘2减1是将这个坐标范围从[0,1]转换到了[-1,1],对应世界坐标。然后使用传入的mvp逆矩阵_inversemvp乘以这个坐标值,就得到了屏幕点的世界坐标。最后将pos的xyz分量除以w分量,这里w分量表示因为远近而产生的缩放值.
5、在计算过世界坐标之后,对于y小于0的坐标要做一下处理,将效果限制在海平面(sea level)之上,使用射线平面相交方程(ray-plane intersection formula)的简化版本来处理.
6、最后根据距离返回色彩值.
如果要实现夜幕降临倒计时的效果,只需要在控制脚本(c#)中获取camera上的nightfall组件,根据时间修改radius变量即可.
以上所述是小编给大家介绍的c#使用shader实现夜幕降临倒计时的效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我网站的支持! 。
原文链接:http://blog.csdn.net/ecidevilin/article/details/52930701 。
最后此篇关于C#使用Shader实现夜幕降临倒计时的效果的文章就讲到这里了,如果你想了解更多关于C#使用Shader实现夜幕降临倒计时的效果的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
背景: 我最近一直在使用 JPA,我为相当大的关系数据库项目生成持久层的轻松程度给我留下了深刻的印象。 我们公司使用大量非 SQL 数据库,特别是面向列的数据库。我对可能对这些数据库使用 JPA 有一
我已经在我的 maven pom 中添加了这些构建配置,因为我希望将 Apache Solr 依赖项与 Jar 捆绑在一起。否则我得到了 SolarServerException: ClassNotF
interface ITurtle { void Fight(); void EatPizza(); } interface ILeonardo : ITurtle {
我希望可用于 Java 的对象/关系映射 (ORM) 工具之一能够满足这些要求: 使用 JPA 或 native SQL 查询获取大量行并将其作为实体对象返回。 允许在行(实体)中进行迭代,并在对当前
好像没有,因为我有实现From for 的代码, 我可以转换 A到 B与 .into() , 但同样的事情不适用于 Vec .into()一个Vec . 要么我搞砸了阻止实现派生的事情,要么这不应该发
在 C# 中,如果 A 实现 IX 并且 B 继承自 A ,是否必然遵循 B 实现 IX?如果是,是因为 LSP 吗?之间有什么区别吗: 1. Interface IX; Class A : IX;
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在阅读标准haskell库的(^)的实现代码: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 a -> b ->a expo x0
我将把国际象棋游戏表示为 C++ 结构。我认为,最好的选择是树结构(因为在每个深度我们都有几个可能的移动)。 这是一个好的方法吗? struct TreeElement{ SomeMoveType
我正在为用户名数据库实现字符串匹配算法。我的方法采用现有的用户名数据库和用户想要的新用户名,然后检查用户名是否已被占用。如果采用该方法,则该方法应该返回带有数据库中未采用的数字的用户名。 例子: “贾
我正在尝试实现 Breadth-first search algorithm , 为了找到两个顶点之间的最短距离。我开发了一个 Queue 对象来保存和检索对象,并且我有一个二维数组来保存两个给定顶点
我目前正在 ika 中开发我的 Python 游戏,它使用 python 2.5 我决定为 AI 使用 A* 寻路。然而,我发现它对我的需要来说太慢了(3-4 个敌人可能会落后于游戏,但我想供应 4-
我正在寻找 Kademlia 的开源实现C/C++ 中的分布式哈希表。它必须是轻量级和跨平台的(win/linux/mac)。 它必须能够将信息发布到 DHT 并检索它。 最佳答案 OpenDHT是
我在一本书中读到这一行:-“当我们要求 C++ 实现运行程序时,它会通过调用此函数来实现。” 而且我想知道“C++ 实现”是什么意思或具体是什么。帮忙!? 最佳答案 “C++ 实现”是指编译器加上链接
我正在尝试使用分支定界的 C++ 实现这个背包问题。此网站上有一个 Java 版本:Implementing branch and bound for knapsack 我试图让我的 C++ 版本打印
在很多情况下,我需要在 C# 中访问合适的哈希算法,从重写 GetHashCode 到对数据执行快速比较/查找。 我发现 FNV 哈希是一种非常简单/好/快速的哈希算法。但是,我从未见过 C# 实现的
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化
1. 绪论 在前面文章中提到 空间直角坐标系相互转换 ,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换。这个就是我们经常在测绘数据处理中,WGS-84坐标系、54北京坐标系
在软件开发过程中,有时候我们需要定时地检查数据库中的数据,并在发现新增数据时触发一个动作。为了实现这个需求,我们在 .Net 7 下进行一次简单的演示. PeriodicTimer .
二分查找 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
我是一名优秀的程序员,十分优秀!