unity shader3d 什么shader的渲染级别比ugui的级别高

Unity3D教程:教你如何利用Shader来进行3D角色的渲染 | Unity3D教程手册
当前位置 :
>> Unity3D教程:教你如何利用Shader来进行3D角色的渲染
Unity3D教程:教你如何利用Shader来进行3D角色的渲染
本文主要介绍一下如何利用Shader来渲染游戏中的3D角色,以及如何利用Unity提供的Surface Shader来书写自定义Shader。
一、从Shader开始
1、通过Assets-&Create-&Shader来创建一个默认的Shader,并取名“MyShader”。
Unity3D教程:3D角色的渲染
2、将MyShader打开即可看见Unity默认的Shader代码
&&&01Shader &Custom/MyShader& {02Properties {03_MainTex (&Base (RGB)&, 2D) = &white& {}04}05SubShader {06Tags { &RenderType&=&Opaque& }07LOD 20008CGPROGRAM09#pragma surface surf Lambert10sampler2D _MainTex;11struct Input {12float2 uv_MainTex;13};14void surf (Input IN, inout SurfaceOutput o) {15half4 c = tex2D (_MainTex, IN.uv_MainTex);16o.Albedo = c.rgb;17o.Alpha = c.a;18}19ENDCG20}21FallBack &Diffuse&22}
3、将该Shader赋给一个角色,就可以看到该Shader所能表达出的Diffuse渲染效果。
Unity3D教程:3D角色的渲染
4、接来我们将以此默认Shader作为蓝本,编写出自定义的Shader。另外,该Shader所用到的参数,我们将在下一章节进行说明。
二、实现多种自定义渲染效果
1、 BumpMap效果
如果想实现Bump Map效果,可对上述的Shader做如下修改:
1.1 在属性Properties中加入:
&&&1Properties {2_MainTex (&Base (RGB)&, 2D) = &white& {}3_BumpMap(&Bumpmap&, 2D) = &bump& {}4}
1.2 在SubShader的变量中也进行相应修改:
&&&1sampler2D _MainTex;2sampler2D _BumpMap;3struct Input {4float2 uv_MainTex;5float2 uv_BumpMap;6};
1.3 最后修改surf函数,加入对Normal分量的计算:
&&&1void surf (Input IN, inout SurfaceOutput o) {2&white-space:&& half4 c = tex2D (_MainTex, IN.uv_MainTex);3o.Albedo = c.rgb;4o.Alpha = c.a;5o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));6}
这样,角色的材质部分即可变为如下形式(暂定BumpMap的Shader名为“MyShader1”):
Unity3D教程:3D角色的渲染
然后,根据Base图来创建其Normal Map图,并拖入到BumpMap中即可。BumpMap的效果显示如下:
Unity3D教程:3D角色的渲染
(1)首先是title的解释
&&&1Shader &Custom/MyShader1&
这种表示表明了该Shader在编辑器中的显示位置,例如我们可在如下地方找到该Shader。
Unity3D教程:3D角色的渲染
(2)其次是Properties
&&&1Properties {2_MainTex (&Base (RGB)&, 2D) = &white& {}3_BumpMap(&Bumpmap&, 2D) = &bump& {}4}
Properties可通过如下语义进行声明:
name ("displayname", property type) = default value
“name” 是与Shader脚本中对应的名字
“display name”是在材质视图中所显示的名字
“propertytype”是指该property的类型,一般可有如下几种类型:Range,Color,2D,Rect,Cube,Float和Vector
“defaultvalue”是指该property的默认值
这里需要注意的是,如果你在Properties中加入了新的属性,那么你需要在CGPROGRAM中的SubShader中加入同样名字的参数。
(3)接下来是“LOD”语义词的解释。
这里的“LOD”主要是指Shader的LOD程度,即对于超出该范围的物体将不再通过该Shader进行渲染,具体的Shader LOD说明可以参见:
(4)我们在SubShader中还加入了
&&&1sampler2D _BumpMap;2float2 uv_BumpMap;
其中,_BumpMap是为了关联Properties中的_BumpMap属性。
而uv_BumpMap,是为了获取BumpMap图中的uv坐标。
(5)最后,我们在surf函数中获取每个顶点的纹理信息以及法线信息,这些信息将被应用于接下来的Vertex Fragment和Pixel Fragment。
&&&1void surf (Input IN, inout SurfaceOutput o) {2half4 c = tex2D (_MainTex, IN.uv_MainTex);3o.Albedo = c.rgb;4o.Alpha = c.a;5o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));6}
其中,tex2D函数可以读取纹理_MainTex中的IN.uv_MainTex坐标位置的像素颜色值。
Albedo和Alpha分别获取该像素的RGB值和Alpha值,其中“Albedo”是一个漫反射参数,它表示一个表面的漫反射能力,即一个表面上出射光强与入射光强的比值。具体介绍可见:。
2、& Blinn-Phong效果
如果想实现Blinn-Phong效果,可对上述的Shader做如下修改:
2.1&&在属性Properties中加入:
&&&1_AmbientColor (&Ambient Color&, Color) = (0.1, 0.1, 0.1, 1.0)2_SpecularColor (&Specular Color&, Color) = (0.12, 0.31, 0.47, 1.0)3_Glossiness (&Gloss&, Range(1.0,512.0)) = 80.0
2.2&&在SubShader的变量中也加入相应修改:
&&&1fixed4 _AmbientColor;2fixed4 _SpecularColor;3half _Glossiness;
2.3&&最后修改surf函数,进行如下修改:
&&&1fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
这里将原有的half4替换为fixed4,这样做是为了提高渲染的性能,因为fixed的精度较之half要低,更高的精度意味着更大的计算量,而这里fixed的精度已经足够,所以使用fixed替代half4,从而来降低计算消耗,增加渲染性能。
2.4&&将“#pragma surface surf Lamber”改成“#pragma surfacesurf CustomBlinnPhong”,同时加入与其对应的LightingCustomBlinnPhong函数来计算顶点光照。
&&&01inline fixed4 LightingCustomBlinnPhong (SurfaceOutput s, fixed3 lightDir, fixed3 viewDir, fixed atten) 02{03fixed3 ambient = s.Albedo * _AmbientColor.rgb;04&05fixed NdotL = saturate(dot (s.Normal, lightDir)); 06fixed3 diffuse = s.Albedo * _LightColor0.rgb * NdotL;07&08fixed3 h = normalize (lightDir + viewDir); 09float nh = saturate(dot (s.Normal, h)); 10float specPower = pow (nh, _Glossiness);11fixed3 specular = _LightColor0.rgb * specPower * _SpecularColor.rgb;12&13fixed4 c;14c.rgb = (ambient + diffuse + specular) * (atten * 2);15c.a = s.Alpha + (_LightColor0.a * _SpecularColor.a * specPower * atten);16return c;17}
该函数的名称为什么不是“CustomBlinnPhong”呢?这是因为该函数虽然是由“#pragma surface surf CustomBlinnPhong”来调用,但是为了让该函数可以正常工作,我们需要在其名称前加入“Lighting”关键字,这样Unity才能识别出这是一个自定义的光照函数。
通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader2”):
Unity3D教程:3D角色的渲染
其显示效果如下:
Unity3D教程:3D角色的渲染
3、& 边缘光照(Rim Light)和卡通渲染(Toon Shading)
可以通过对上述Shader做以下改进,来达到这种效果:
3.1&&在属性Properties中加入:
&&&1_RimColor (&Rim Color&, Color) = (0.12, 0.31, 0.47, 1.0) 2_RimPower (&Rim Power&, Range(0.5, 8.0)) = 3.0 3_Ramp (&Shading Ramp&, 2D) = &gray& {}
3.2&&在SubShader的变量中也加入相应修改:
&&&01sampler2D _MainTex;02sampler2D _BumpMap;03sampler2D _Ramp;04&05fixed4 _AmbientColor;06fixed4 _SpecularColor;07half _Glossiness;08&09fixed4 _RimColor;10half _RimPower;11&12struct Input {13float2 uv_MainTex;14float2 uv_BumpMap;15half3 viewDir; 16};
3.3&&修改surf函数,进行如下修改:
&&&1void surf (Input IN, inout SurfaceOutput o) {2fixed4 c = tex2D (_MainTex, IN.uv_MainTex);3o.Albedo = c.rgb;4o.Alpha = c.a;5o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));6fixed rim = 1.0 - saturate (dot (normalize(IN.viewDir), o.Normal));7o.Emission = (_RimColor.rgb * pow (rim, _RimPower));8}
这里主要是用来计算边缘光照的,首先通过视线与法线的夹角来找到模型的边缘,然后再根据距离的远近来控制发射光的强度。
3.4&&将“#pragma surface surf CustomBlinnPhong”改成“#pragma surfacesurf CustomBlinnPhong exclude_path:prepass”,同时在LightingCustomBlinnPhong函数来修改漫反射光的计算,来达到卡通渲染的效果。
&&&1fixed NdotL = saturate(dot (s.Normal, lightDir)); 2fixed diff = NdotL * 0.5 + 0.5;3fixed3 ramp = tex2D (_Ramp, float2(diff, diff)).rgb;4fixed diffuse = s.Albedo * LightColor0.rgb * ramp;
通过以上设置,角色的材质部分即可变为如下形式(暂定该Shader名为“MyShader3”):
Unity3D教程:3D角色的渲染
其显示效果如下:
Unity3D教程:3D角色的渲染
可以看出边缘光照的效果,同时还可以看出明显的明暗变化的卡通渲染效果。
三、&&&&&&&小结
综上所述,本文已经给出了人物的几种基本渲染方法及其Shader实现,在这里我并没有去分析每种渲染效果的原理,而仅是从实际出发,直接给出对应的简单实现方法。如果想要对光照模型进行深入理解,可以Google搜索其原理进行了解。最后,给出各种渲染方法的对比图,显示如下:
Unity3D教程:3D角色的渲染
本系列文章由&Unity公司开发支持工程师Amazonzx&编写,。
【上一篇】
【下一篇】
您可能还会对这些文章感兴趣!Unity3dCG语言编写Shader之渲染管线 - 简书
Unity3dCG语言编写Shader之渲染管线
引言shader到底是干什么用的?shader的工作原理是什么?shader中文名叫着色器,顾名思义,它的作用可以先简单理解为给屏幕上的物体画上颜色。而什么东西负责给屏幕上画颜色?当然是GPU,所以我们写shader的目的就是告诉GPU往屏幕哪里画、怎么画。说到这其实大家应该很明白了,如果我们连GPU的工作原理都不知道,何谈指挥它?
GPU的渲染管线又是什么?渲染管线也称为渲染流水线或像素流水线或像素管线,是显示芯片内部处理图形信号相互独立的的并行处理单元。在某种程度上可以把渲染管线比喻为工厂里面常见的各种生产流水线,工厂里的生产流水线是为了提高产品的生产能力和效率,而渲染管线则是提高显卡的工作能力和效率。
正文所谓GPU的渲染管线,听起来好像很高深的样子,其实我们可以把它理解为一个流程,就是我们告诉GPU一堆数据,最后得出来一副二维图像,而这些数据就包括了”视点、三维物体、光源、照明模型、纹理”等元素。在各种图形学的书中,渲染管线主要分为三个阶段:应用程序阶段、几何阶段、光栅阶段。
一、应用程序阶段这个阶段相对比较好理解,就比如我们在Unity里开发了一个游戏,其实很多底层的东西Unity都帮我们实现好了,例如碰撞检测、视锥剪裁等等,这个阶段主要是和CPU、内存打交道,在把该计算的都计算完以后,在这个阶段的末端,这些计算好的数据(顶点坐标、法向量、纹理坐标、纹理)就会通过数据总线传给图形硬件,作为我们进一步处理的源数据。
二、几何阶段主要负责顶点坐标变换、光照、裁剪、投影以及屏幕映射,改阶段基于GPU进行运算,在该阶段的末端得到了经过变换和投影之后的顶点坐标、颜色、以及纹理坐标。简而言之,几何阶段的主要工作就是“变换三维顶点坐标”和“光照计算”。问题随之而来,为什么要变换顶点坐标?我是这么理解的,比如你有一个三维游戏场景,场景中的每个模型都可以用一个向量来确定它的位置,但如何让计算机根据这些坐标把模型正确的、有层次的画在屏幕上?这就是我们需要变换三维顶点坐标的原因,最终目的就是让GPU可以将这些三维数据绘制到二维屏幕上。根据顶点坐标变换的先后顺序,主要有如下几个坐标空间:Object space,模型坐标空间;World space,世界坐标空间;Eye space,观察坐标空间;Clip and Project space,屏幕坐标空间。下图就是GPU的整个处理流程,深色区域就是顶点坐标空间的变换流程,大家了解一下即可,我们需要关注的是每个坐标空间的具体含义和坐标空间之间转换的方法。
坐标空间的含义与坐标空间的转换
2.1、从object space到world spaceobject space有两层核心含义,第一,object space中的坐标值就是模型文件中的顶点值,这些值是在建立模型时得到的,例如一个.max文件,里面包含的数据就是object space的坐标。第二,object space的坐标与其他物体没有任何参照关系,这是object space和world space区分的关键。world space坐标的实际意义就有有一个坐标原点,物体跟坐标原点相比较才能知道自己的确切位置。例如在unity中,我们将一个模型导入到场景中以后,它的transform就是世界坐标。
2.2、从world space到eye space所谓eye space,就是以摄像机为原点,由视线方向、视角和远近平面,共同组成的一个梯形体,如下图,称之为视锥(viewing frustum)。近平面,是梯形体较小的矩形面,也是靠近摄像机的平面,远平面就是梯形体较大的矩形,作为投影平面。在这个梯形体的内的数据是可见的,超出的部分会被视点去除,也叫视锥剪裁。例如在游戏中的漫游功能,屏幕的内容随摄像机的移动而变化,这是因为GPU将物体的顶点坐标从world space转换到了eye space。
2.3、从eye space到project and clip spaceeye space坐标转换到project and clip space坐标的过程其实就是一个投影、剪裁、映射的过程。因为在不规则的视锥体内剪裁是一件非常困难的事,所以前人们将剪裁安排到一个单位立方体中进行,这个立方体被称为规范立方体(CCV),CVV的近平面(对应视锥体的近平面)的x、y坐标对应屏幕像素坐标(左下角0、0),z代表画面像素深度。所以这个转换过程事实上由三步组成:(1),用透视变换矩阵把顶点从视锥体变换到CVV中;(2),在CVV内进行剪裁;(3),屏幕映射:将经过前两步得到的坐标映射到屏幕坐标系上。
2.4、primitive assembly(图元装配)和triangle setup(三角形处理)到目前为止我们得到了一堆顶点的数据,这一步就是根据这些顶点的原始连接关系还原出网格结构。网格由顶点和索引组成,这个阶段就是根据索引将顶点链接到一起,组成线、面单元,然后进行剪裁,如果一个三角形超出屏幕以外,例如两个顶点在屏幕内,一个顶点在屏幕外,这时我们在屏幕上看到的就是一个四边形,然后把这个四边形切成两个小的三角形。现在我们得到了一堆在屏幕坐标上的三角形面片,这些面片是用于光栅化的。
三、光栅化阶段。经过上面的步骤之后,我们得到了每个点的屏幕坐标值,和我们需要绘制的图元,但此时还有两个问题:(1)屏幕坐标是浮点数,但像素是用整数来表示的,如何确定屏幕坐标值所对应的像素?(2)如何根据已确定位置的点,在屏幕上画出线段或者三角形?对于问题1,绘制的位置只能接近两指定端点间的实际线段位置,例如,一条线段的位置是(10.48, 20.51),转换为像素位置就是(10,21)。问题2,涉及到具体的画线和填充算法,有兴趣的话可以研究。这个过程结束后,顶点和图元已经对应到像素,之后的流程就是如何处理像素,即给像素赋予颜色值。给像素赋予颜色的阶段称为Pixel Operation,是在更新帧缓存之前,执行最后一系列针对每个片段的操作,其目的是计算出每个像素的颜色值。在这个阶段,被遮挡的面通过一个被称为深度测试的过程消除。pixel operation包含下面这些流程:(1)消除遮挡面;(2)Texture operation,纹理操作,根据像素的纹理坐标,查询对应的纹理值;(3)Blending,通常称为alpha blending,根据目前已经画好的颜色,与正在计算的颜色的alpha值混合,形成新的颜色。(4)Filtering,将正在计算的颜色经过某种滤镜后输出。该阶段之后,像素的颜色值被写入帧缓存中。原文链接:
狗狗,被黑了12345678910
搜索配件:
&&价格区间:从
价格:¥49.90 元
最近30天销量:月销 5 笔
商品来源:
&购物咨询(商品客服):
由卖家 智源图书专营店 从 北京 发货
推荐服务商:&&&&&&&&&&
商品详情图
商品标签云
买过的人评价...
卖家:当当网官方旗舰店
来自:北京
最近30天销量:0件
相关内容:&
卖家:博瑞祥隆图书专营店
来自:北京
最近30天销量:5件
相关内容:&
卖家:奥维博世图书专营店
来自:北京
最近30天销量:1件
相关内容:&
卖家:恒久图书专营店
来自:北京
最近30天销量:0件
相关内容:&
卖家:杰城图书专营店
来自:福建 福州
最近30天销量:17件
相关内容:&
¥69.00(7.1折)
卖家:济南常青藤图书专营店
来自:山东 济南
最近30天销量:0件
相关内容:&
卖家:兴阅图书专营店
来自:北京
最近30天销量:100件
相关内容:&
¥98.00(7.1折)
卖家:杰城图书专营店
来自:福建 福州
最近30天销量:7件
相关内容:&
¥69.00(7.8折)
卖家:中图天下图书专营
来自:北京
最近30天销量:10件
相关内容:&
¥109.00(7.2折)
卖家:兴阅图书专营店
来自:北京
最近30天销量:2件
相关内容:&
¥42.00(9.2折)
卖家:瑞雅图书专营
来自:广东 广州
最近30天销量:37件
相关内容:&
¥148.00(7.3折)
卖家:智源图书专营店
来自:北京
最近30天销量:1件
相关内容:&
双氙商品标签云画像 正在为您生成中,请稍候再来哟...
您或许还喜欢
59.30&&&&(无折)
52.30&&&&(无折)
50.10&&&&(无折)
45.80&&&&(7.8折)
48.80&&&&(无折)
44.80&&&&(6.5折)
48.30&&&&(无折)
33.80&&&&(8.7折)
请留下你对双氙的意见或建议,感谢!
(如果有个人或商家的相关问题需要解决或者投诉,请致电400-000-5668)
联系电话/微信/QQ:
支持中英文(Support in both Chinese and English)
感谢您的反馈,我们会努力做得更好!你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
小弟我在shader里面做了一个随距离渐变的vs和fs,简答的说就是离摄像头近的地方透明通道为0, 距离离摄像头越远,透明通道逐渐增加,直到物体完全显示。shader的rendertype和renderqueue都是transparent对于单个物体来说,这样可以做到渐变显示的效果。但是对于多个物体有重叠的时候,透明效果很奇怪。
具体情况如下:
面对摄像头,有两个球,这两个球面对摄像机有重叠的部分(观察透明效果是否生效)。每个球有自己的mat,每个mat都用了我的shader。当球1在球2前面并且球1是半透明的时候,球2可以从摄像头角度看出来(球1透明生效)。但是当球2 在球1面前并且球2是半透明的时候,球1被球2遮挡住的部分,全部都看不到了(球2透明挂了。。)。 同样的shader,我猜是不是自己写的shader会和u3d自带的画透明物体的机制冲突了。。 有哪位大侠碰到过类似的情况么?自己的shader和引擎的shader有冲突?
在线等,挺急的这个问题,还想不出怎么解决~~ 谢谢各位高手~~
这是我的shader 两个球用的是同一个shader。我是用的shaderlab的最基本的vs fs来写的,没用surface shader。大侠帮忙看看,非常感谢~~
Shader "Distance Alpha Blend" {
Properties {
_Color ("Main Color", Color) = (.5,.5,.5,1)
_EmissionColor ("Main Emission Color", Color) = (1, 1, 1, 1)
_OutlineColor ("Outline Color", Color) = (0,0,0,1)
_Outline ("Outline width", Range (0.002, 0.05)) = 0.003
_MainTex ("Base (RGB)", 2D) = "white" { }
_ToonShade ("ToonShader Cubemap(RGB)", CUBE) = "" { Texgen CubeNormal }
_CamPos ("Camera Pos(World Space Pos)", Vector) = (0, 0, 0, 0)
_CamDir ("Camera Dir(need to normalize)", Vector) = (0, 0, 1, 0)
_NearDis ("Near Distance", float) = 5.0
_FarDis ("Far Distance", float) = 10.0
SubShader {
Name "BASE"
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// Basic Draw
sampler2D _MainT
samplerCUBE _ToonS
fixed4 _MainTex_ST;
fixed4 _EmissionC
// Transparent Effect
fixed4 _CamP
fixed4 _CamD
fixed _NearD
fixed _FarD
struct appdata {
fixed4 vertex : POSITION;
fixed2 texcoord : TEXCOORD0;
fixed3 normal : NORMAL;
struct v2f {
fixed4 pos : POSITION;
fixed4 color : COLOR;
fixed3 cubenormal : TEXCOORD0;
fixed2 texcoord1 : TEXCOORD1;
fixed4 texcoord2 : TEXCOORD2;
fixed2 texcoord3 : TEXCOORD3;
fixed2 texcoord4 : TEXCOORD4;
v2f vert (appdata i)
v2f o = (v2f)0;
o.texcoord2 = mul(_Object2World, i.vertex);
o.pos = mul (UNITY_MATRIX_MVP, i.vertex);
o.texcoord1 = TRANSFORM_TEX(i.texcoord, _MainTex);
o.cubenormal = mul (UNITY_MATRIX_MV, fixed4(i.normal,0));
fixed4 frag (v2f i) : COLOR
float4 vertWorld = i.texcoord2;
fixed vertPlaneD = _CamDir.x * vertWorld.x + _CamDir.y * vertWorld.y + _CamDir.z * vertWorld.z;
fixed3 nearPoint = _CamPos.xyz + _CamDir.xyz * _NearD
fixed3 farPoint = _CamPos.xyz + _CamDir.xyz * _FarD
fixed nearPlaneD = _CamDir.x * nearPoint.x + _CamDir.y * nearPoint.y + _CamDir.z * nearPoint.z;
fixed farPlaneD = _CamDir.x * farPoint.x + _CamDir.y * farPoint.y + _CamDir.z * farPoint.z;
fixed4 col = _Color * tex2D(_MainTex, i.texcoord1) ;
fixed4 cube = texCUBE(_ToonShade, i.cubenormal);
if (vertPlaneD <= nearPlaneD)
return fixed4(0, 0, 0, 0);
fixed4 col = _Color * tex2D(_MainTex, i.texcoord1) ;
fixed4 cube = texCUBE(_ToonShade, i.cubenormal);
if ( vertPlaneD
nearPlaneD)
return fixed4(2.0f * cube.rgb * col.rgb * _EmissionColor.rgb,
_Color.a * (vertPlaneD - nearPlaneD)/ (farPlaneD - nearPlaneD + 0.0001));
if (vertPlaneD > farPlaneD)
return fixed4(2.0f * cube.rgb * col.rgb * _EmissionColor.rgb, _Color.a);
return fixed4(2.0f * cube.rgb * col.rgb * _EmissionColor.rgb, _Color.a);
Fallback "Diffuse"
半透明问题一直是渲染的一个难点,效率,渲染顺序,效果等综合各个方面。
Unity自己封装了一套Shader的框架就是ShaderLab这个玩意,具体你可以去看文档!
直接放出你写的Shader吧,帮你看看问题在哪!
要回复问题请先或
浏览: 1851
关注: 2 人}

我要回帖

更多关于 unity shader 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信