Unity的unity5 实时阴影影效率低吗

【岚依】【教程】免费版其实没那么差!至少【阴影】可以搞!_unity3d吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:62,902贴子:
【岚依】【教程】免费版其实没那么差!至少【阴影】可以搞!收藏
好,也许还有一些人不知道如何在免费版里烘焙阴影,那么我就发个帖说说吧~呐,我也在用免费版,现在没有阴影。。。
达内unity3d培训全程&实战教学&,unity3d专家讲师授课.免费unity3d课程试听中!到达内unity3d学院学习unity3d,只需4个月速成unity3d游戏工程师.
好了,在Inspector里选中Directional Light,把Shadow打开,这时unity会提示你“免费版里不能使用实时阴影”嗯,实时阴影unity免费版里的确是不能搞,但是unity官方却把顶尖的Beast光影烘培技术让免费版也可以使用,这样就很好了。(尽管只能烘焙静态阴影。。。)
现在,在Window菜单中打开LightMapping。
啊对,在继续之前,先得确定准备烘焙光影的物体是否为静态(Static),或者说,在光照贴图上呈静态。
好,继续,开始烘焙。开始烘培后unity右下角将会出现烘焙的进度。同时,大家可能在任务管理器里发现一个新进程:thebeast.对,就是楼上所讲的the beast,一个很好的光影烘焙系统。烘焙的时间取决于需要烘焙的物体以及电脑的性能,可能需要好几分钟。
嗯,好了!看到了吗?这是阴影!!!!!!!!液~~看看被圈出来的地方~~
牛叉了以前怎么也搞不好,原来还要设个静态
。。。。。。。为啥我这可以用那个选项。。。。。。。。。。。
那不就是要分好uv吗?但是地面的话都是重复贴图啊怎么渲染阴影啊??
unity3d千锋VR培训0元入学,「高薪」就业!「预约申请2周免费试学」.火爆预约中!千锋VR培训,招生限大专以上学历,年龄30岁以下,符合条件即可报名,入学即签订就业协议!
特地来顶,烘培不但是免费的福利,其实场景制作至少现阶段都得了解
我用盗版Pro版的
就算用pro,对于建筑之类的静态的东西阴影放好光之后烘培,这样搞一大堆灯的时候貌似可以不卡。。。
请你看看有没有什么地方搞错了……
检查一下我圈起来的地方。你可以清楚地看见,我用的是免费版(License Type:Unity);其实,即使你要用Pro版或者破解版,静态阴影还是很重要的:相对于实时阴影,静态阴影质量更高,占用的资源也更小。
又学到了一点,顶你!
当时的蓝衣还很羞涩~~~
求pro版的阴影在哪里
请问下为什么我在准备烘焙的时候,就是最后一步点击确认的时候,发现旁边的color space 为lightmaps阿?
就是这样的:
大神你还在么。。。我用的4.5破解版木有阴影,砸破?
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或游戏开发(4)
shader(1)
unity3D(3)
图形编程(2)
UnityEffects系列(1)
UnityEffects(2)之(2)ProjectorShadow(手游上的实时阴影方案)
上一篇说到了在unity5.x中实现shadowMap的方法()。但是由于它需要使用DepthTexture有一定的硬件要求(参考这里:),而且是一个posteffect(后期效果),在手机上面还是效率不高。
手游上面的人物阴影一般都是比较取巧的方法(毕竟没有这么多人用机皇:),基本上遵循“够用就好,看起来不错就好”的原则),一种是给人物脚底贴一个黑圈圈,第二种是使用projector。第一种就不提了,效果不好。这里我们就讨论一下后者,使用投影来实现手游中的实时阴影。据说猪场的《功夫熊猫3》中的阴影也是使用类似的方法实现的,效果不错,但是阴影投影到台阶这种不接受阴影的物体就会有一点小穿帮,也是这种方式的一个缺点,如下图:
建筑物等静态物体产生的阴影一般用光照烘焙来实现,这里就不讨论了。
江湖惯例先贴图:
工程放在:&使用unity5.4
场景是Scene/(2)ProjectorShadow
实现的原理和shadowMap差不多,只不过不生成深度图,而是使用replaceShader生成一张“轮廓”图,使用untiy自带的Projector组件投影到场景中,在shader中计算从而生成阴影效果。使用replaceShader是为了避免渲染“轮廓”图的时候还是用原来复杂的shader,照成不必要的性能浪费。替换后我们只输出纯色(方便测试)或者alpha值到“轮廓”图。
我们生成的“轮廓”图:
投影的时候只需要判断该像素的alpha值,alpha为0的不在阴影中,alpha值越小阴影越透明。
由于原理和上一篇差不多就不做过多解释了,这里列两点比较值得注意的:
1、渲染“轮廓”图的相机视锥(光锥)的生成方式我们使用了通过场景的包围盒来校正的方法,这种方式比较适合手游,毕竟多数手游需要动态阴影的就是那些人物(其他的都是静态阴影通过光照烘培来实现),这样最大化的利用的这张“轮廓”图,提高了阴影的质量。对应方法是ShadowUtils. SetLightCamera(Bounds b, Camera lightCamera)
参考资料:
2、当“轮廓”图中的物体贴近边缘的时候阴影会产生bug,如下图,看到阴影被拉长了一条。
这是由于“轮廓”图的wrapMode采用使用了clamp导致的,clamp模式就是uv在超过1的时候把图像边缘的像素拉伸,如下图:
如何解决呢?两个方法。
1)求包围盒的时候设置一个offset,使包围盒向外扩大一点,这样物体就不会贴着“轮廓”图的边缘了
2)在投影器的shader中使用一张图来做遮罩(下图),这样边缘的像素可以过滤掉,还可以做出边缘的阴影渐隐的效果。
上面两种方法都可以从代码中找到。
下面我们来对比一下shadowMap,分析一下各自的优缺点:
通用,物体穿透不会穿帮,能很好的处理遮挡关系。
1.依赖DepthTexture,浮点深度图,有一点硬件需求。
有硬件要求:
2.unity中深度图不能单独输出,要手动写shader从自带的depthMap中取出深度来保存,比较麻烦。使用替换渲染时,不产生阴影的物体必须替换为白色,不替换会默认黑色,然后黑色又是深度最小值,会使得物体都处于阴影之中,不好控制。
ps:其实1和2都可以通过自定义shader直接将深度渲染到纹理来避免使用自带的_CameraDepthTexture,这样可以忽略硬件的限制。在上一篇有提到:
unity为移动平台生成shadowMap似乎也是用的类似的方法。如下图,感兴趣的读者可以阅读UnityCG.cginc相关代码:
3.产生和接受阴影的物体都要渲染到深度图
4.比较深度的误差偏移有可能根据平台而不太一样
5.要为接受阴影的物体提供shader
6.不支持半透明物体的阴影
ProjectorShadow
1.不依赖DepthTexture
2.不用为接受阴影的物体提供shader
3.只需要渲染产生阴影的物体
4.性能比shadowMap有优势
5.支持半透明物体阴影,如下图:
1.是一个trick,不通用
2.不能处理物体对阴影的遮挡,接受阴影的物体和产生阴影的物体有穿透时会穿帮
总体来说ProjectorShadow比较适合移动平台,能模拟出效果不错的实时阴影
扩展:还可以使用pcf优化阴影边界
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:4977次
排名:千里之外
评论:15条
(1)(2)(1)(1)我发现unity5测试版的光照贴图不能融合实时阴影了_unity3d吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:62,902贴子:
我发现unity5测试版的光照贴图不能融合实时阴影了收藏
不知道为什么,5beta里的光照贴图不能融合实时阴影,不知道是不是我哪里设置错了,之前unity4的时候都是可以融合的,难道是测试版的bug?这也太不科学了,而且我不知道如何用那个GI来实现环境遮光,直接渲染的效果感觉都达不到我要求的效果,不知道有没有其他人玩5beta版的
达内unity3d培训全程&实战教学&,unity3d专家讲师授课.免费unity3d课程试听中!到达内unity3d学院学习unity3d,只需4个月速成unity3d游戏工程师.
玩了一天5,新建了一个cube,电脑崩了三次,移动端实时光照很开心,加了个天空盒子,天上各种黑洞,无奈,删了,等beta5以上再战!
如果弄这个效果的,可以分享下吗??
萌萌的场景!
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或Unity局部高效实时阴影 - 简书
Unity局部高效实时阴影
无意间看到一篇文章,说是Unity5 demo中为了实现角色的良好阴影,单独给角色设计了一个角色阴影系统。而且使用的是比较老的技术,但效果很好。其实在很多时候,我们需要的并不是万能的阴影光照系统,而是局部能做到效果就行。
万能的好处在于任何情况都能看上去合理,但是相对的,性能开销也大,同时为了兼顾各种情况,只能做各种效果的折中,所以我们看到了现在移动平台上,要么就是没有实时阴影,要么就是充满锯齿的实时阴影,要么就是使用2D贴图来模拟实时阴影。用2D贴图来模拟的效果毫无疑问是最好的,但问题在于成本太高,很多小团队资金有限,很难专门为每一个角色都让美术画一大堆阴影贴图。而这也毫无疑问会增加游戏的大小。我主要思考的是,在某种条件下,是否可以实现局部的良好的阴影。比如角色展台,毫无疑问只会出现一个角色,那么这个情况下,毫无疑问我们需要的是一个完美的阴影。或者说某一些游戏,视角固定,而且能看到的范围很小,那么是否只针对这个部分去实现好的阴影系统。或者一个很小的室内,我们也需要一个好的角色阴影。ok,那么开始思考方案,首先我们应该只需要一个平行光的阴影。一般来说需要获得这个位置看过去的深度图。我首先在这个位置上放了一个正交摄像机,注意如果你想让角色有阴影,那么必须让角色处在这个正交摄像机的范围内,那么现在第一个问题来了,如何保证角色在正交摄像机的范围内?方法如下:首先你要获得你主摄像机内的所有的需要阴影的物体,然后将这些物体转化到正交摄像机的坐标中,计算出这些物体的最大范围,并得出正交矩阵赋值给正交摄像机。(代码借鉴了,对这个楼主深表感谢)这里要注意,Unity计算出来的Z是负值,但OpenGL是正的,官方说明如下:Matrix that transforms from world to camera space.Use this to calculate the camera space position of objects or to provide customcamera's location that is not based on the transform.Note that camera space matches OpenGL convention: camera's forward is the negativeZ axis. This is different from Unity's convention, where forward is the positive Zaxis.If you change this matrix, the camera no longer updates its rendering based on its Transform.This lasts until you call ResetWorldToCameraMatrix.
#pragma strict
// Offsets camera's rendering from the transform's position.
public var offset: Vector3 = new Vector3(0, 1, 0);
var camera: C
function Start() {
camera = GetComponent.();
function LateUpdate() {
var camoffset: Vector3 = new Vector3(-offset.x, -offset.y, offset.z);
var m: Matrix4x4 = Matrix4x4.TRS(camoffset, Quaternion.identity, new Vector3(1, 1, -1));
camera.worldToCameraMatrix = m * transform.worldToLocalM
不过实际使用过程中,我们也许并不需要正确的矩阵赋值,因为你需要的是保证所有的物体在摄像机范围内,只需要知道AABB盒,然后把相机设置在AABB盒的中心,同时增加Size即可。
public ListCharactorL
void CreateCameraProjecterMatrix()
Vector3 v3MaxPosition = -Vector3.one * f;
Vector3 v3MinPosition = Vector3.one * f;
for (int vertId = 0; vertId & CharactorList.C ++vertId)
// Light view space
Vector3 v3Position = camera1.worldToCameraMatrix.MultiplyPoint3x4(CharactorList[vertId].position);
if (v3Position.x & v3MaxPosition.x)
v3MaxPosition.x = v3Position.x;
if (v3Position.y & v3MaxPosition.y)
v3MaxPosition.y = v3Position.y;
if (v3Position.z & v3MaxPosition.z)
v3MaxPosition.z = v3Position.z;
if (v3Position.x & v3MinPosition.x)
v3MinPosition.x = v3Position.x;
if (v3Position.y & v3MinPosition.y)
v3MinPosition.y = v3Position.y;
if (v3Position.z & v3MinPosition.z)
v3MinPosition.z = v3Position.z;
Vector3 off = v3MaxPosition - v3MinP
Vector3 sizeOff =
sizeOff.z = 0;
float dis = sizeOff.
//CreateOrthogonalProjectMatrix (ref m_projMatrix, v3MaxPosition, v3MinPosition);
//Debug.Log (v3MaxPosition.ToString() + v3MinPosition.ToString());
//Matrix4x4 m = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1, 1, -1));
//camera1.projectionMatrix = m * m_projM
camera1.orthographicSize = dis / 1.8f;
camera1.farClipPlane = off.z + 50;
void CreateViewMatrix(ref Matrix4x4 viewMatrix,Vector3 look,Vector3 up,Vector3 right,Vector3 pos)
look.Normalize ();
up.Normalize ();
right.Normalize ();
float x = -Vector3.Dot (right,pos);
float y = -Vector3.Dot (up,pos);
float z = -Vector3.Dot (look,pos);
viewMatrix.m00 = right.x; viewMatrix.m10 = up.x; viewMatrix.m20 = look.x; viewMatrix.m30 = 0.0f;
viewMatrix.m01 = right.y; viewMatrix.m11 = up.y; viewMatrix.m21 = look.y; viewMatrix.m31 = 0.0f;
viewMatrix.m02 = right.z; viewMatrix.m12 = up.z; viewMatrix.m22 = look.z; viewMatrix.m32 = 0.0f;
viewMatrix.m03 = viewMatrix.m13 = viewMatrix.m23 = viewMatrix.m33 = 1.0f;
void CreateOrthogonalProjectMatrix(ref Matrix4x4 projectMatrix,Vector3 v3MaxInViewSpace, Vector3 v3MinInViewSpace)
float scaleX, scaleY, scaleZ;
float offsetX, offsetY, offsetZ;
scaleX = 2.0f / (v3MaxInViewSpace.x - v3MinInViewSpace.x);
scaleY = 2.0f / (v3MaxInViewSpace.y - v3MinInViewSpace.y);
offsetX = -0.5f * (v3MaxInViewSpace.x + v3MinInViewSpace.x) * scaleX;
offsetY = -0.5f * (v3MaxInViewSpace.y + v3MinInViewSpace.y) * scaleY;
scaleZ = 1.0f / (v3MaxInViewSpace.z - v3MinInViewSpace.z);
offsetZ = -v3MinInViewSpace.z * scaleZ;
projectMatrix.m00 = scaleX; projectMatrix.m01 = 0.0f; projectMatrix.m02 = 0.0f; projectMatrix.m03 = offsetX;
projectMatrix.m10 = 0.0f; projectMatrix.m11 = scaleY; projectMatrix.m12 = 0.0f; projectMatrix.m13 = offsetY;
projectMatrix.m20 = 0.0f; projectMatrix.m21 = 0.0f; projectMatrix.m22 = scaleZ; projectMatrix.m23 = offsetZ;
projectMatrix.m30 = 0.0f; projectMatrix.m31 = 0.0f; projectMatrix.m32 = 0.0f; projectMatrix.m33 = 1.0f;
你看 所有角色都被包括在内了。当然具体适合的值你可以自己调整,这样我们就解决了第一个问题。 如果你的应用场景在室内,你可以无视第一个问题,直接手动设置一个最合适的值就行了。第二部,就是我们需要获得物体的剪影。就是说将物体的外轮廓给检录下来。当然复杂点就是获得物体的深度图。剪影获得很简单,我们看下深度图如何获得。因为在移动平台上不支持自动生成深度图,所以我打算自己使用片段着色器获得。
Shader "depthShader" {
Properties {
SubShader {
//Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members pos1)
#pragma exclude_renderers d3d11 xbox360
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D_float _CameraDepthT
struct appdata {
float4 vertex : POSITION;
struct v2f {
half4 pos : SV_POSITION;
v2f vert (appdata_base v) {
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
o.depth = o.pos.
fixed4 frag(v2f i) : COLOR
float d = i.depth.x/i.depth.y;
float flag = 0;
d = abs(d);
float3 kEncodeMul = float3(1.0, 255.0, 65025.0);
float kEncodeBit = 1.0/255.0;
float3 enc = kEncodeMul *
enc = frac (enc);
enc -= enc.yzz * kEncodeB
return fixed4(flag, enc);
本来只要存储z就好了,不过很遗憾的是,有些平台的z竟然是负值,负值存储成像素是无意义的。所以我用r存储正负值,gba保存数值,但这样子性能确实会下降,毕竟在片段着色器里,考虑到后面需要照顾阴影质量,我觉得不使用深度图,而使用剪影。剪影就简单了,连着色器都不用自己写,直接用摄像机渲染的黑图即可。这里我将摄像机设置成普通渲染模式,手动调用render,将贴图放到rendertexture中。
camera1 = GameObject.Find ("Camera").
//camera1.hideFlags = HideFlags.HideAndDontS
camera1.enabled =
//camera1.projectionMatrix = camera.projectionM
int textureSize = 1024;
shadowTexture = new RenderTexture(textureSize , textureSize, 16, RenderTextureFormat.ARGB32);
shadowTexture.name = "shadowTexture" + GetInstanceID();
shadowTexture.isPowerOfTwo =
shadowTexture.hideFlags = HideFlags.DontS
camera1.targetTexture = shadowT
这样就可以看到如下贴图:
1024大小,内存6M 还算可以接受。当然,因为深度没有用,可以取消,这样会变成4M,其他格式可能会更小,但手机上不一定支持,所以暂时先这样吧。第三个问题,就是怎么把这些东西投射到地上变成影子。首先投射到地上已经有现成的Projector组件了,所以问题变成了坐标计算。我们先把Projector的位置确定一下,Projector应该和主摄像机放在同一个地方,同时有同样的参数设置:
proj = GameObject.Find ("GameObject").GetComponent();
proj.nearClipPlane = camera.nearClipP
proj.farClipPlane = camera.farClipP
proj.fieldOfView = camera.fieldOfV
这样就保证了视角内的物体都会出现阴影。然后就是坐标计算了,我们想一下,假设世界坐标中的点a,那么我们计算出它在正交摄像机中的坐标,然后根据坐标取出投影贴图中的点,那么假如这个点是全黑的(看你设置的是啥值了),那么就是不在阴影区的,假如不是,那么说明是阴影。有了这个方案,我们就开始计算吧。首先我们可以轻易获得物体的坐标,问题在于怎么获得它在正交摄像机中的坐标,这个就需要使用正交摄像机的矩阵获得:
matVP = GL.GetGPUProjectionMatrix (camera1.projectionMatrix, true) * camera1.worldToCameraM
proj.material.SetMatrix("ShadowMatrix", matVP);
注意,我将这个计算出来的矩阵赋值给了一个材质,这个材质就是Projector使用的,因为是它需要根据坐标判断是否有阴影。这样似乎接下来就可以直接写出着色器了:
v2f vert (appdata_base v)
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
float4x4 matWVP = mul (ShadowMatrix, _Object2World);
o.uvShadow = mul(matWVP, v.vertex);
注意,顶点着色器不仅要计算出pos,同时还要获得正交相机中的坐标,也就是uvShadow.然后就可以在片段着色器中处理了:
half2 uv = i.uvShadow.xy / i.uvShadow.w * 0.5 + 0.5;
#if UNITY_UV_STARTS_AT_TOP
uv.y = 1 - uv.y;
fixed4 res = fixed4(0, 0, 0, 0);
fixed4 texS = tex2D(_ShadowTex, uv);
if(texS.a & 0)
res.a = 0.5;
就这么几行,阴影就出现了:
但效果似乎不那么尽如人意,让我们看下u3d自带的高品质的阴影效果:
其实已经很接近了呢,不过鉴于我开头宣称要高质量阴影,所以我打算继续优化边缘,因为你可以看到边缘部分的锯齿,当然我们可以单纯增加贴图大小,但是假如到2048,那么就要占据16M的内存了,所以我暂时打算用另外一种做法,pcf。就是通过采样,将边缘像素模糊化。
texS = tex2D(_ShadowTex, uv + half2(-0./pad, -0./pad));
if(texS.a & 0)
res.a += _S
texS = tex2D(_ShadowTex, uv + half2(0./pad, -0./pad));
if(texS.a & 0)
res.a += _S
texS = tex2D(_ShadowTex, uv + half2(-0./pad, -0./pad));
if(texS.a & 0)
res.a += _S
texS = tex2D(_ShadowTex, uv + half2(0./pad, 0./pad));
if(texS.a & 0)
res.a += _S
经过采样后效果如下:
最后 是时候做一次全面比较了,在电脑上我自己写的完爆自带的,因为我的电脑的显卡很渣,但手机显卡好一些,所以手机上的结果可能不太一样,放到手机上,开启最强模式,看看到底性能和效果对比吧。找了一台两年前的1000块钱的华为:u3d 高质量阴影:近距离效果:
再看我自己实现的效果:2048最强模式下:近距离:
不过帧数下降了不少,再看看1024的吧。
效果也是要好上不少吧。后来做了一些优化,主要是动态调整正交摄像机的位置, 这样就能够在远距离时候使用模糊阴影,近距离使用高清阴影了, 在我们自己的项目中使用, 效果十分可以。优化代码:
public class VisibleMesh:MonoBehaviour
void OnWillRenderObject()
if(Camera.current == Camera.main)
if(SceneShadow.inst.CharactorList.Contains(tr))
SceneShadow.inst.CharactorList.Add (tr);
Vector3 off = v3MaxPosition - v3MinP
Vector3 pos = (v3MaxPosition + v3MinPosition) / 2;
pos = camera1.cameraToWorldMatrix.MultiplyPoint3x4 (pos);
camera1.transform.position = pos - camera1.transform.forward * (off.z + 10);
Vector3 sizeOff =
sizeOff.z = 0;
float dis = sizeOff.x;
if(sizeOff.y & dis)
dis = sizeOff.y;
camera1.orthographicSize = dis / 2;
camera1.farClipPlane = off.z + 30;
Don't reinvent the wheel.

我要回帖

更多关于 实时阴影shader unity 的文章

 

随机推荐