unity中有什么unity shader教程可以绘制出cube的六条棱?

Unity 法线贴图、高光贴图、Cube Map shader
Unity 相关纹理贴图
写unity shader有些时候了,出于寂寞,拿出来晒晒吧!!!!
先看一下Unity 法线贴图、高光贴图、Cube Map shader最终效果:
说老实话,我不怎么喜欢看教程,我喜欢自己捉摸捉摸,要知道自己捉摸出来的东西那个高兴劲儿,恨不得全城人都跟我一起hi一把。这个多纹理shader写了有几个月了,当然还有其他一同出炉的shader。
什么是漫反射光照
先看一下Unity中Lighting.cginc文件,
哦,对!!这就是漫反射,不过我不喜欢这么就用在vert
fragment shader中,而且unity他自己喜欢他的surface shader。
说白了漫反射的数学就是光线与法线的关系,
用用cos(光线,法线)来算出它在不同地方的强度
当然根据量子力学,光线与物体表面做了能量交换,光这种电磁波频率受到影响,所以这个cos要乘以rgb,也可以理解为物体表面颜色强度变化。
法线贴图、高光贴图、Cube Map ##
我就不那么多说了,我以下只会贴出关键实现代码,因为其他博客都有过,我想我的博客因该基于它们做深层次实现,当然一切都是原创,不过还是要看理论的东西和一些语法,其他都好说。
这是必备的纹理,你给美工说就是了。。。。它会懂得。。
法线贴图代码
先解算法线贴图的数值,用用UnpackNormal就行了,他其实就是把(0,1)的颜色值算到(-1,1)中,当然要注意法线是保存在AG通道中的,AG=法线的xy,z可以用勾股定理算出,当然可以用其他值来代替,比如我用法线深度值来代替,方便了美工的调节;最后在算到模型的切线空间做光照。
高光贴图代码
这这这,就相当的简单了,当你看到高光贴图时,我是第一想到的算法是白色的地方就是光线可以反射的地方。于是就这么直接算算纹理和高光。
CubeMap代码
这儿先对应他的颜色。。。
cubmap 就是反射周围的颜色,所以借助高光纹理的通道乘以cube颜色,就表示光泽的地方才反射。
cube/2 是降低反射颜色的亮度,不然我不喜欢这么亮,当然交给美工也可以哟!!!
按照量子理论的思想来说,多种光照的影响下它们在物体表面有各自的状态,所以这儿代码为:
所以在数学上的表示为各种光照相加。。。。。
一切代码原型
Shader "Custom/mul Shader" {
Properties {
_MainTex ("主纹理 (RGB)", 2D) = "white" {}
_bump ("法线贴图", 2D) = "white" {}
_BunpZ ("法线深度调节", Range(0.0, 1.0)) = 0.0
_Specular ("高光贴图", 2D) = "white" {}
_SpeRange ("高光范围", Range(0.0, 20.0)) = 1.0
_specularColor ("高光颜色", Color) = (1.0, 1.0, 1.0, 1.0)
_HeighMap ("视差贴图", 2D) = "white" {}
_Height ("视差深度", Range(0.005, 0.08)) = 0.02
_Cubemap ("Cube Map", CUBE) = "grey"
SubShader {
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase" "Queue"="Overlay"}
Zwrite Off
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex
float4 _MainTex_ST
sampler2D _bump
fixed _BunpZ
sampler2D _Specular
half _SpeRange
fixed4 _specularColor
sampler2D _HeighMap
fixed _Height
samplerCUBE _Cubemap
fixed3 _LightColor0
struct vertIN{
float4 vertex : POSITION
fixed2 tex : TEXCOORD0
fixed3 normal : NORMAL
fixed3 tangent : TANGENT
struct vertOUT{
float4 pos : SV_POSITION
half2 uv : TEXCOORD0
fixed3 nDir : NORMAL
fixed3 tDir : TANGENT
fixed3 bDir : BINORMAL
fixed3 LDir : TEXCOORD1
fixed3 rDir : TEXCOORD2
fixed3 vDir : TEXCOORD3
fixed3 reflectDir : TEXCOORD4
//float3 view : TEXCOORD4
vertOUT vert(vertIN i){
o.pos = mul(UNITY_MATRIX_MVP,i.vertex)
o.uv = TRANSFORM_TEX(i.tex,_MainTex)
o.nDir = normalize(mul(float4(i.normal,0),_World2Object).xyz)
o.tDir = normalize(mul(_Object2World,float4(i.tangent,0)).xyz)
o.bDir = normalize(cross(o.nDir,o.tDir))
o.LDir = normalize(_WorldSpaceLightPos0)
o.rDir = normalize(reflect(-o.LDir,o.nDir))
o.vDir = normalize(WorldSpaceViewDir(i.vertex))
o.reflectDir = normalize(reflect(-o.vDir,o.nDir))
//o.view = WorldSpaceViewDir(i.vertex)
fixed4 frag(vertOUT ou):COLOR{
//half h = tex2D(_HeighMap,ou.uv).w
//float2 offset = ParallaxOffset(h,_Height,ou.vDir)
half2 uv = ou.uv
fixed4 c = tex2D(_MainTex,uv)
fixed Diff = saturate(dot(ou.nDir,ou.LDir))
fixed3 bump = UnpackNormal(tex2D(_bump,uv))
bump.z = _BunpZ
fixed3x3 TangentSpace = fixed3x3(
fixed3 bumpDir = normalize(mul(TangentSpace,bump))
fixed bumpDiff = max(0,dot(ou.LDir,bumpDir))
fixed3 specular = tex2D(_Specular,uv)
fixed specularDiff = bumpDiff*pow(dot(ou.rDir,ou.vDir),_SpeRange)
fixed3 cube = texCUBE(_Cubemap,ou.reflectDir)/2
c.rgb *=(bumpDiff*_LightColor0 + specularDiff*specular*_specularColor + cube*specular.g)
//FallBack "Diffuse"
呵呵,一不小心贴出来罗,我觉得你能懂这些光照原理,在多的代码算什么。
换一种角度去思考,不然看http://www.shadertoy.com 的代码时,你就知道了。。。以后我会叙述我移植其中的一个代码。我觉得移植它们的神代码是件不道德事,因为我还不如自己写写学习。
这是自己写的原版满反射
这是多纹理作用
这些代码对有的会的人说没难度
但我想shader这个东西它是有思想的,每个人的想法不同,
看过本文的人也看了:
我要留言技术领域:
取消收藏确定要取消收藏吗?
删除图谱提示你保存在该图谱下的知识内容也会被删除,建议你先将内容移到其他图谱中。你确定要删除知识图谱及其内容吗?
删除节点提示无法删除该知识节点,因该节点下仍保存有相关知识内容!
删除节点提示你确定要删除该知识节点吗?Access denied | www.bkjia.com used Cloudflare to restrict access
Please enable cookies.
What happened?
The owner of this website (www.bkjia.com) has banned your access based on your browser's signature (b576ca-ua98).主题 : unity shader reflect
级别: 侠客
可可豆: 296 CB
威望: 286 点
在线时间: 185(时)
发自: Web Page
来源于&&分类
unity shader reflect&&&
改编自《cg教程--可编程实时图形学权威指南》上的demo。本文的目的不在于教你如何实现反射效果,而是在于让你学会迁移cg、hlsl、glsl到unity中[unity shader 资料很少,但是前面哪几种还是相对较多的 ]反射向量计算公式 R=I-2N(N*I) 备注N*I是点乘   I入射光线,N法向量函数实现:float3 reflect(float3 I,float3 N){  return I-2.0*N*dot(N,I);}Shader &CG shader Reflect&{&&&& Properties {&&&&&&&&&&&&&&&&&&&&&&&&environmentMap(&Environment Map&, Cube) = && {}&&&&&&&&&&&&&&&&&&reflectivity(&reflectivity1&, float) =1 //反射系数&&决定反射强度&&&&&&&&&&&&&&&&&&decalMap(&decalMap&, 2D) = &white& {}&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&SubShader{&&&&&&&&&&&&&&&&&&&&&&Pass{&&&&&&&&&&&&&&&&&&&&&&&&&& CGPROGRAM&&&&&&&&&&&&&&&&&&&&&&&&&& #pragma vertex vert //顶点编程入口&&&&&&&&&&&&&&&&&&&&&&&&&& #pragma fragment frag //片段编程入口&&&&&&&&&&&&&&&&&&&&&&&&&& #include &UnityCG.cginc& //注意引入&&&&&&&&&&&&&&&&&&&&&&&&&& struct VertInput{&&//在UnityCG中有定义 可以参考appdata_base、appdata_tan、appdata_full&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float4 position:POSITION;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float2 texCoordw:TEXCOORD0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float3 normal1:NORMAL;&&&&&&&&&&&&&&&&&&&&&&&&&& };&&&&&&&&&&&&&&&&&&&&&&&&&& struct VertOutput{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float4 oPosition:SV_POSITION;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float2 oTexCoord:TEXCOORD0;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float3 R:TEXCOORD1;&&&&&&&&&&&&&&&&&&&&&&&&&& };&&&&&&&&&&&&&&&&&&&&&&&&&& // uniform 类型的参数 需要在Properties里面定义&&&&&&&&&&&&&&&&&&&&&&&&&& uniform samplerCUBE environmentM&&&&&&&&&&&&&&&&&&&&&&&&&& unifor&&&&&&&&&&&&&&&&&&&&&&&&&& uniform sampler2D decalM&&&&&&&&&&&&&&&&&&&&&&&&&& VertOutput vert(VertInput input)&&&&&&&&&&&&&&&&&&&&&&&&&& {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& VertO&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& o.oPosition=mul(UNITY_MATRIX_MVP,input.position);//UNITY_MATRIX_MVP变量, 就是对应图形中的模型视图投影矩阵(ModelViewProj),unity中规定 必须这么写&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& o.oTexCoord=input.texC&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float3 positionW=mul(_Object2World,input.position).//_Object2World 模型矩阵,把本地坐标转到世界坐标&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float3 N=mul((float3x3)_Object2World,input.normal1);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& N=normalize(N);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float3 I=positionW-_WorldSpaceCameraP//计算入射光线,需要在世界坐标系中计算。_WorldSpaceCameraPos视点在世界坐标的位置&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& o.R=reflect(I,N);//计算反射光线 reflect系统自带函数&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&& float4 frag(VertOutput output):COLOR&&&&&&&&&&&&&&&&&&&&&&&&&& {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float4 reflectionColor=texCUBE(environmentMap,output.R);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float4 decalColor=tex2D(decalMap,output.oTexCoord);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& float4 color1=lerp(decalColor,reflectionColor,reflectivity);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& return color1;&&&&&&&&&&&&&&&&&&&&&&&&&& }&&&&&&&&&&&&&&&&&&&&&&&&&& ENDCG&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}}上例代码出现的_Object2World,_WorldSpaceCameraPos 莫名奇妙的参数,来自UnityCG.cginc文件,在对cg、hlsl、glsl进行移植的时候,特殊参数需要参考UnityCG.cginc文件的定义。附unity shader 学习资料:
级别: 新手上路
可可豆: 22 CB
威望: 22 点
在线时间: 2(时)
发自: Web Page
好东西,支持下
级别: 新手上路
可可豆: -3 CB
威望: -3 点
在线时间: 0(时)
发自: Web Page
顶下再看哈http://www.mm165.net  
级别: 新手上路
可可豆: 61 CB
威望: 61 点
在线时间: 1(时)
发自: Web Page
不错的哦,顶一下
最有价值的开发 http://www.unitymanual.com
关注本帖(如果有新回复会站内信通知您)
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 关注CVP公众号
扫一扫 浏览移动版Unity Shader编程_图文_百度文库
您的浏览器Javascript被禁用,需开启后体验完整功能,
享专业文档下载特权
&赠共享文档下载特权
&10W篇文档免费专享
&每天抽奖多种福利
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Unity Shader编程
&&98jy.net创始人化石老师写的Unity3d Shader编程。详细讲述了Unity3d的ShaderLab结构和相关的实例。Shader的中文书籍中,值得一读。
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩170页未读,
定制HR最喜欢的简历
你可能喜欢【浅墨Unity3D Shader编程】之五 圣诞夜篇: Unity中Shader的三种形态对比&混合操作合辑
时间: 18:02:24
&&&& 阅读:1014
&&&& 评论:
&&&& 收藏:0
标签:& 本系列文章由&出品,转载请注明出处。&& 文章链接: 作者:毛星云(浅墨)&& &微博: 邮箱:&本文算是固定功能Shader的最后一篇,下一次更新应该就会开始讲解表面Shader,而讲解完表面Shader,后续文章最终会讲解到顶点着色器和片段着色器(也就是可编程Shader)。文章第一部分复习和进一步了解了Unity中Shader的三种形态,然后讲解了固定功能Shader中混合操作的方方面面,然后以6个Shader的书写作为实战内容,最后创建了一个温馨美好的圣诞夜场景进行了Shader的测试。&依旧是国际惯例,先上本文配套程序的截图吧。圣诞节就快到了,而下次更新就已经过了圣诞节,于是这次更新浅墨就提前把这个场景放出来吧,预祝大家圣诞节快乐~&雪花飘落:&&可爱的圣诞雪人:&&精心装扮的圣诞树:&&&月是故乡明:&雾气弥漫:OK,图先就上这么多。文章末尾有更多的运行截图,并提供了源工程的下载。可运行的exe下载在这里:&&&&好的,我们正式开始。一、再谈Unity中Shader的三种形态因为Unity中基础的固定功能Shader的知识点基本上讲完,下期开始就要准备讲表面着色器(Surface Shader)了,所以在文章开头,让我们复习和更深入了解一下Unity中Shader的三种形态。&在Unity中,Shader便可以分成如下三种基本类型:&&1.固定功能着色器(FixedFunction Shader)&2.表面着色器(SurfaceShader)&3.顶点着色器&片段着色器(Vertex Shader & Fragment Shader)&&&顾名思义,其中的固定功能着色器便是我们所说的固定功能渲染管线(fixed-functionrenderingpipelines)的具体表现,而表面着色器、顶点着色器以及片段着色器便属于可编程渲染管线。下面分别对其进行简单的介绍。&&&&&1.1& Unity中的Shader形态之一:固定功能Shader&&这里的固定功能着色器可以说是Unity为Shader的书写自带的一层壳,Unity已经在内部为我们做了大量的工作,我们只要稍微记住一些关键字、一些规范就可以实现出很多不错的效果。固定功能着色器是我们初学Unity Shader的最近几篇文章中的主要学习对象。而后面的表面着色器、顶点着色器以及片段着色器就是在固定功能着色器的基础上嵌套了CG语言的代码而成的更加复杂的着色器。我们来看看他们的一些基本概念。固定管线是为了兼容老式显卡。都为顶点光照,就是我们前四篇文章加上这篇文章中讲到的内容。其特征是里面的核心是下面Material材质属性块、没有CGPROGRAM和ENDCG块,以及各种顶点着色和片段着色的宏命令。&一个光照材质完备版的固定功能Shader示例如下:&Shader &浅墨Shader编程/Volume5/固定功能的Shader示例&
//-------------------------------【属性】-----------------------------------------
Properties
_Color (&主颜色&, Color) = (1,1,1,0)
_SpecColor (&高光颜色&, Color) = (1,1,1,1)
_Emission (&自发光颜色&, Color) = (0,0,0,0)
_Shininess (&光泽度&, Range (0.01, 1)) = 0.7
_MainTex (&基本纹理&, 2D) = &white& {}
//--------------------------------【子着色器】--------------------------------
//----------------通道---------------
//-----------材质------------
//可调节的漫反射光和环境光反射颜色
Diffuse [_Color]
Ambient [_Color]
Shininess [_Shininess]
//高光颜色
Specular [_SpecColor]
//自发光颜色
Emission [_Emission]
//开启光照
Lighting On
//开启独立镜面反射
SeparateSpecular On
//设置纹理并进行纹理混合
SetTexture [_MainTex]
Combine texture * primary DOUBLE, texture * primary
我们将此Shader编译后赋给材质,得到如下效果:&实际场景中的测试效果:&&&1.2 Unity中的Shader形态之二:表面着色器SurfaceShader&&这部分算是Unity微创新自创的一套着色器标准。表面着色器(Surface Shader)这个概念更多的只是在Unity中听说,可以说是Unity自己发扬光大的一项使Shader的书写门槛降低和更易用的技术。我们会在接下来的学习中逐渐意识到Unity是如何为我们把Shader的复杂性包装起来,使其书写的过程更便捷和易用的。一些特性如下:&?&&&&& SurfaceShader可以认为是一个光照Shader的语法块、一个光照VS/FS的生成器。减少了开发者写重复代码的需要。?&&&&& 特征是在SubShader里出现CGPROGRAM和ENDCG块。(而不是出现在Pass里。因为SurfaceShader自己会编译成多个Pass。)?&&&&& 编译指令是:#pragma surface surfaceFunction lightModel[optionalparams]o&&&& surfaceFunction:surfaceShader函数,形如void surf (Input IN, inoutSurfaceOutput o)o&&&& lightModel:使用的光照模式。包括Lambert(漫反射)和BlinnPhong(镜面反射)。?&&&& 也可以自己定义光照函数。比如编译指令为#pragma surface surf MyCalc?&&&& 在Shader里定义half4 LightingMyCalc (SurfaceOutputs, 参数略)函数进行处理(函数名在签名加上了“Lighting”)。? & & &我们自己定义输入数据结构(比如上面的Input)、编写自己的Surface函数处理输入、最终输出修改过后的SurfaceOutput。而SurfaceOutput的定义为:struct SurfaceOutput
half3 A // 纹理颜色值(r, g, b)
half3 N // 法向量(x, y, z)
half3 E // 自发光颜色值(r, g, b)
half S // 镜面反射度
half G // 光泽度
half A // Alpha不透明度
};&上面是一些特性总结,让我们看一个具体Shader示例:&Shader &浅墨Shader编程/Volume5/表面Shader示例 &
//-------------------------------【属性】-----------------------------------------
Properties
_MainTex (&【纹理】Texture&, 2D) = &white& {}
_BumpMap (&【凹凸纹理】Bumpmap&, 2D) = &bump& {}
_RimColor (&【边缘颜色】Rim Color&, Color) = (0.17,0.36,0.81,0.0)
_RimPower (&【边缘颜色强度】Rim Power&, Range(0.6,9.0)) = 1.0
//----------------------------【开始一个子着色器】---------------------------
//渲染类型为Opaque,不透明
Tags { &RenderType& = &Opaque& }
//-------------------开始CG着色器编程语言段-----------------
//使用兰伯特光照模式
#pragma surface surf Lambert
//输入结构
struct Input
float2 uv_MainT//纹理贴图
float2 uv_BumpM//法线贴图
float3 viewD//观察方向
//变量声明
sampler2D _MainT//主纹理
sampler2D _BumpM//凹凸纹理
float4 _RimC//边缘颜色
float _RimP//边缘颜色强度
//表面着色函数的编写
void surf (Input IN, inout SurfaceOutput o)
//表面反射颜色为纹理颜色
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).
//表面法线为凹凸纹理的颜色
o.Normal = UnpackNormal (tex2D (_BumpMap, IN.uv_BumpMap));
//边缘颜色
half rim = 1.0 - saturate(dot (normalize(IN.viewDir), o.Normal));
//边缘颜色强度
o.Emission = _RimColor.rgb * pow (rim, _RimPower);
//-------------------结束CG着色器编程语言段------------------
//“备胎”为普通漫反射
Fallback &Diffuse&
}&我们将此Shader编译后赋给材质,得到如下效果:&调各种颜色玩一玩:&&&&而实际场景中的测试效果(对应于一开始的金色):&1.3 Unity中的Shader形态之三:可编程Shader&可编程Shader其实就是顶点着色器和片段着色器,这一部分和DirectX系的HLSL和CG着色器语言联系紧密。其实就是Unity给HLSL和CG报了一个ShaderLab的壳。研究过Direct3D和OpenGL着色器编程的童鞋们一定对顶点着色器和片段着色器不陌生。我们来简单介绍一下他们的用途。顶点着色器:产生纹理坐标,颜色,点大小,雾坐标,然后把它们传递给裁剪阶段。片段着色器:进行纹理查找,决定什么时候执行纹理查找,是否进行纹理查找,及把什么作为纹理坐标。&可编程Shader的特点为: 功能最强大、最自由的形态。特征是在Pass里出现CGPROGRAM和ENDCG块编译指令#pragma。详见。其中重要的包括:
#pragma vertex name
#pragma fragment name
替换name,来指定Vertex
Shader函数、Fragment Shader函数。
#pragma target name
替换name(为2.0、3.0等)。设置编译目标shader model的版本。
#pragma only_renderers name name ...
#pragma exclude_renderers name name...
#pragma only_renderers gles gles3,
#pragma exclude_renderers d3d9 d3d11 opengl,
只为指定渲染平台(render platform)编译
关于引用库。通过形如#include &UnityCG.cginc&引入指定的库。常用的就是UnityCG.cginc了。其他库详见。ShaderLab内置值。Unity给Shader程序提供了便捷的、常用的值,比如下面例子中的UNITY_MATRIX_MVP就代表了这个时刻的MVP矩阵。详见。Shader输入输出参数语义(Semantics)。在管线流程中每个阶段之间(比如Vertex Shader阶段和FragmentShader阶段之间)的输入输出参数,通过语义字符串,来指定参数的含义。常用的语义包括:COLOR、SV_Position、TEXCOORD[n]。完整的参数语义可见(由于是HLSL的连接,所以可能不完全在Unity里可以使用)。特别地,因为Vertex Shader的的输入往往是管线的最开始,Unity为此内置了常用的数据结构:
appdata_base
顶点着色器输入位置、法线以及一个纹理坐标。
appdata_tan
顶点着色器输入位置、法线、切线以及一个纹理坐标。
appdata_full
顶点着色器输入位置、法线、切线、顶点颜色以及两个纹理坐标。
appdata_img
顶点着色器输入位置以及一个纹理坐标。 &&让我们用一个可编程着色器Shader示例结束此部分的讲解:&Shader &浅墨Shader编程/Volume5/可编程Shader示例&
//-------------------------------【属性】--------------------------------------
Properties
_Color (&Color&, Color) = (1.0,1.0,1.0,1.0)
_SpecColor (&Specular Color&, Color) = (1.0,1.0,1.0,1.0)
_Shininess (&Shininess&, Float) = 10
//--------------------------------【子着色器】--------------------------------
//-----------子着色器标签----------
Tags { &LightMode& = &ForwardBase& }
//----------------通道---------------
//-------------------开始CG着色器编程语言段-----------------
#pragma vertex vert
#pragma fragment frag
//---------------声明变量--------------
uniform float4 _C
uniform float4 _SpecC
uniform float _S
//--------------定义变量--------------
uniform float4 _LightColor0;
//--------------顶点输入结构体-------------
struct vertexInput
float4 vertex : POSITION;
float3 normal : NORMAL;
//--------------顶点输出结构体-------------
struct vertexOutput
float4 pos : SV_POSITION;
float4 col : COLOR;
//--------------顶点函数--------------
vertexOutput vert(vertexInput v)
//一些方向
float3 normalDirection = normalize( mul( float4(v.normal, 0.0), _World2Object ).xyz );
float3 viewDirection = normalize( float3( float4( _WorldSpaceCameraPos.xyz, 1.0) - mul(_Object2World, v.vertex).xyz ) );
float3 lightD
float atten = 1.0;
lightDirection = normalize(_WorldSpaceLightPos0.xyz);
float3 diffuseReflection = atten * _LightColor0.xyz * max( 0.0, dot( normalDirection, lightDirection ) );
float3 specularReflection = atten * _LightColor0.xyz * _SpecColor.rgb * max( 0.0, dot( normalDirection, lightDirection ) ) * pow( max( 0.0, dot( reflect( -lightDirection, normalDirection ), viewDirection ) ), _Shininess );
float3 lightFinal = diffuseReflection + specularReflection + UNITY_LIGHTMODEL_AMBIENT;
//计算结果
o.col = float4(lightFinal * _Color.rgb, 1.0);//颜色
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);//位置
//--------------片段函数---------------
float4 frag(vertexOutput i) : COLOR
//-------------------结束CG着色器编程语言段------------------
Fallback &Diffuse&
}我们将此Shader编译后赋给材质,得到如下效果:&可以发现就算这么简单的可编程Shader其细节效果也是非常出色,比固定功能Shader和表面Shader都看起来高端。我们依然是调各种颜色玩一玩:&&&实际场景中的测试效果:&&OK,下面我们来看本次文章的主角——blending操作。&&&&二、混合操作(Blending)&我们直奔主题吧。混合操作最常见的用途便是用来制作透明物体、或者是进行纹理的混合。它是Shader渲染的最后一步:如上图所示,正被渲染的像素经过顶点光照、顶点着色器、剔除和深度测试,雾效、Alpha测试等一系列操作之后,最后一步便是混合操作。这个时候计算结果即将被输出到帧缓冲中。而混合操作,就是管理如何将这些像素输出到帧缓存中的这样一个过程——是直接替换原来的,是一加一的混合,还是有Alpha参与的不等比地混合等等。混合操作有两个对象:源和目标,因此也有两个对应的因子,即源因子和目标因子(对应于下面讲解的Blend SrcFactor DstFactor操作)。而如果我们把RGB颜色通道和Alpha通道分开来操作的话,混合就有了4个操作对象(对应于下面讲解的Blend SrcFactor DstFactor,SrcFactorA DstFactorA操作)。&2.1 混合操作相关的句法&Blend OffTurn off blending&关闭混合Blend&SrcFactorDstFactor基本的配置并启动混操作。对产生的颜色乘以SrcFactor.对 已存在于屏幕的颜色乘以DstFactor,并且两者将被叠加在一起。&Blend&SrcFactorDstFactor,&SrcFactorA DstFactorA同上,但是使用不同的要素来混合alpha通道,也就是有了4个操作对象&BlendOp&Add /Min | Max | Sub | RevSub此操作不是Blend操作一样添加混合颜色在一起,而是对它们做不同的操作。而如下便是常用混合操作符(blend operations)的含义列举:
将源像素和目标像素相加.
用源像素减去目标像素
用目标像素减去源像素
取目标像素和源像素颜色的较小者作为结果
取目标像素和源像素颜色的较大者作为结果 &&2.2 混合因子(Blend factors)列举&以下所有的属性都可作为SrcFactor或DstFactor。其中,Source指的是被计算过的颜色,Destination是已经在屏幕上的颜色。One值为1,使用此因子来让帧缓冲区源颜色或是目标颜色完全的通过。Zero值为0,使用此因子来删除帧缓冲区源颜色或目标颜色的值。SrcColor使用此因子为将当前值乘以帧缓冲区源颜色的值SrcAlpha使用此因子为将当前值乘以帧缓冲区源颜色Alpha的值。DstColor使用此因子为将当前值乘以帧缓冲区源颜色的值。DstAlpha使用此因子为将当前值乘以帧缓冲区源颜色Alpha分量的值。OneMinusSrcColor使用此因子为将当前值乘以(1 -帧缓冲区源颜色值)OneMinusSrcAlpha使用此因子为将当前值乘以(1 -帧缓冲区源颜色Alpha分量的值)OneMinusDstColor使用此因子为将当前值乘以(1 –目标颜色值)OneMinusDstAlpha使用此因子为将当前值乘以(1 –目标Alpha分量的值)2.3 常见的混合操作句法示例&上面都是一些句法和列表的列举,往往会令人一头雾水,下面这是一些示例,用其中的任何一句加在Pass中就可以实现对应的混合操作了:&Blend SrcAlpha OneMinusSrcAlpha
// Alpha混合
Blend One One
Blend One OneMinusDstColor
// 比较柔和的相加(SoftAdditive)
Blend DstColor Zero
Blend DstColor SrcColor
// 2倍乘法&&三、QianMo‘s Toolkit升级到v1.3&&这次QianMo‘s Toolkit又迎来了新的特性——飞翔。将脚本赋给Controller,并调整相应的速度,(并可以先禁掉之前的鼠标视角控制相关脚本)然后点运行,并可以在天空中自由地飞翔了。其中用W、A、S、D控制前后左右,R、F控制上升下降。&其代码如下://-----------------------------------------------【脚本说明】-------------------------------------------------------
脚本功能:
控制Contorller在场景中飞翔
使用语言:
开发所用IDE版本:Unity4.5 06f 、Visual Studio 2010
2014年12月 Created by 浅墨
更多内容或交流,请访问浅墨的博客:http://blog.csdn.net/poem_qianmo
//---------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------【使用方法】-------------------------------------------------------
第一步:在Unity中拖拽此脚本到场景的Controller之上,或在Inspector中[Add Component]-&[浅墨‘s Toolkit]-&[SetMaxFPS]
第二步:在面板中设置相关鼠标速度
//---------------------------------------------------------------------------------------------------------------------
using UnityE
using System.C
//添加组件菜单
[AddComponentMenu(&浅墨‘s Toolkit/FlyController&)]
public class FlyController : MonoBehaviour
//参数定义
public float lookSpeed = 5.0f;
public float moveSpeed = 1.0f;
public float rotationX = 0.0f;
public float rotationY = 0.0f;
void Update()
//获取鼠标偏移量
rotationX += Input.GetAxis(&Mouse X&) * lookS
rotationY += Input.GetAxis(&Mouse Y&) * lookS
rotationY = Mathf.Clamp(rotationY, -90, 90);
//鼠标控制视角
transform.localRotation = Quaternion.AngleAxis(rotationX, Vector3.up);
transform.localRotation *= Quaternion.AngleAxis(rotationY, Vector3.left);
transform.position += transform.forward * moveSpeed * Input.GetAxis(&Vertical&);
transform.position += transform.right * moveSpeed * Input.GetAxis(&Horizontal&);
//I键,向上平移
if (Input.GetKey(KeyCode.R))
transform.position += transform.up * moveS
//K键,向下平移
if (Input.GetKey(KeyCode.F))
transform.position -= transform.up * moveS
}就这样,我们的QianMo’s Toolkit中的工具越来越多:&&四、Shader书写实战&&1. 纹理载入Shader因为后面几个shader的需要,先根据我们之前所学,几行代码就可以实现一个纹理载入Shader:Shader &浅墨Shader编程/Volume5/18.基本纹理载入&
//-------------------------------【属性】--------------------------------------
Properties
_MainTex (&基本纹理&, 2D) = &black& { }
//--------------------------------【子着色器】--------------------------------
//-----------子着色器标签----------
Tags { &Queue& = &Geometry& } //子着色器的标签设为几何体
//----------------通道---------------
//设置纹理
SetTexture [_MainTex] { combine texture }
}我们将此Shader编译后赋给材质,得到如下效果:&实际场景中的运行效果如下:&&&2.基本blend使用在上面简单的texture载入的Shader的基础上加上一行关于blend的代码,就成了我们今天的第二个Shader:&Shader &浅墨Shader编程/Volume5/19.基本blend使用&
//-------------------------------【属性】-----------------------------------------
Properties
_MainTex (&将要混合的基本纹理&, 2D) = &black& { }
//--------------------------------【子着色器】----------------------------------
//-----------子着色器标签----------
Tags { &Queue& = &Geometry& } //子着色器的标签设为几何体
//----------------通道---------------
//进行混合
Blend DstColor Zero
//设置纹理
SetTexture [_MainTex] { combine texture }
}我们将此Shader编译后赋给材质,得到如下效果:我们采用的是乘法混合操作(& Blend DstColor Zero),可以发现颜色相对于第一个Shader有了稍微的变暗。&虽然肉眼很难看出区别,但实际上的确是有变化的:&&3.基本blend使用+颜色可调再给我们的Shader加上一点可自定义的颜色,并让纹理的alpha通道插值混合顶点颜色& 。代码如下:&Shader &浅墨Shader编程/Volume5/20.基本blend使用+颜色可调&
//-------------------------------【属性】-----------------------------------------
Properties
_MainTex (&将混合的纹理&, 2D) = &black& {}
_Color (&主颜色&, Color) = (1,1,1,0)
//--------------------------------【子着色器】--------------------------------
//-----------子着色器标签----------
Tags { &Queue& = &Transparent& } //子着色器的标签设为透明
//----------------通道---------------
Blend One OneMinusDstColor
// 柔性相加
SetTexture [_MainTex]
// 使颜色属性进入混合器
constantColor [_Color]
// 使用纹理的alpha通道插值混合顶点颜色
combine constant lerp(texture) previous
}&我们将此Shader编译后赋给材质,得到如下效果:&&调成各种颜色:&&&实际场景中的测试效果:&&&&&4.基本blend使用+顶点光照在之前Shader的基础上,给我们的Shader再加上材质属性和顶点光照:Shader &浅墨Shader编程/Volume5/21.基本blend使用+顶点光照&
//-------------------------------【属性】-----------------------------------------
Properties
_MainTex (&Texture to blend&, 2D) = &black& {}
_Color (&主颜色&, Color) = (1,1,1,0)
//--------------------------------【子着色器】--------------------------------
//-----------子着色器标签----------
Tags { &Queue& = &Transparent& }
//----------------通道---------------
//【1】设置材质
Diffuse [_Color]
Ambient [_Color]
//【2】开启光照
Lighting On
Blend One OneMinusDstColor
// Soft Additive
SetTexture [_MainTex]
// 使颜色属性进入混合器
constantColor [_Color]
// 使用纹理的alpha通道插值混合顶点颜色
combine constant lerp(texture) previous
&于是结果如下:&调各种颜色看看:&&&在场景中的测试效果图为:&&&5.实现玻璃效果第二版&之前我们用剔除实现过一版玻璃效果,这次我们来用blend实现完全不一样的玻璃效果,需要载入一个cubemap(其实根据cubemap的选择不同,会实现不同的效果,比如本次的最终效果就有点像金属材质)。Shader的代码如下:Shader &浅墨Shader编程/Volume5/22.玻璃效果v2&
//-------------------------------【属性】--------------------------------------
Properties
_Color (&Main Color&, Color) = (1,1,1,1)
_MainTex (&Base (RGB) Transparency (A)&, 2D) = &white& {}
_Reflections (&Base (RGB) Gloss (A)&, Cube) = &skybox& { TexGen CubeReflect }
//--------------------------------【子着色器】--------------------------------
//-----------子着色器标签----------
Tags { &Queue& = &Transparent& }
//----------------通道---------------
//进行纹理混合
Blend One One
//设置材质
Diffuse [_Color]
Lighting On
//和纹理相乘
SetTexture [_Reflections]
combine texture
Matrix [_Reflection]
我们将此Shader编译后赋给材质,得到如下效果,可以发现最终效果是一个带室内场景反射的金属材质:&实际场景中的测试效果:&6. 实现玻璃效果第三版&我们给上面的第二版加上第二个pass,最终代码如下:Shader &浅墨Shader编程/Volume5/23.玻璃效果v3&
//-------------------------------【属性】-----------------------------------------
Properties
_Color (&Main Color&, Color) = (1,1,1,1)
_MainTex (&Base (RGB) Transparency (A)&, 2D) = &white& {}
_Reflections (&Base (RGB) Gloss (A)&, Cube) = &skybox& { TexGen CubeReflect }
//--------------------------------【子着色器】----------------------------------
//-----------子着色器标签----------
Tags { &Queue& = &Transparent& }
//----------------通道1--------------
Blend SrcAlpha OneMinusSrcAlpha
Diffuse [_Color]
Lighting On
SetTexture [_MainTex] {
combine texture * primary double, texture * primary
//----------------通道2--------------
//进行纹理混合
Blend One One
//设置材质
Diffuse [_Color]
Lighting On
//和纹理相乘
SetTexture [_Reflections]
combine texture
Matrix [_Reflection]
载入同样的纹理和cubemap,得到的效果更加醇厚优异:实际场景中的测试效果:&&OK,这次的Shader实战就是上面的这些了。&&&&五、圣诞夜场景创建就像文章开头中说的,圣诞节就快到了,而下次更新就已经过了圣诞节,于是这次更新浅墨就提前把这个精心准备的圣诞夜场景放出来吧,预祝大家圣诞节快乐~以大师级美工鬼斧神工的场景作品为基础,浅墨调整了场景布局,加入了音乐,并加入了更多高级特效,于是便得到了如此这次温馨美好的场景。而冬天穿衣不便,加上路滑,浅墨故意把controller调出了走路打滑的感觉。运行游戏,圣诞音乐渐渐响起,雪白的雪花静静飘落,我们来到美丽的圣诞夜:&雪花飞扬:&月上树梢:浅墨精心装扮的圣诞树:月光给屋顶披上一层清辉:&&火炉、圣诞礼物:&月是故乡明:&&可爱的圣诞雪人:&浅墨是不会告诉你们是怎么进到门紧关的房子里面来的,自己摸索吧~大雪纷飞的路:&最后放一张这次Shader的全家福:&&OK,美图就放这么多。游戏场景可运行的exe可以在文章开头中提供的链接下载。而以下是源工程的下载链接。 本篇文章的示例程序源工程请点击此处下载:&& & &好的,本篇文章到这里就全部结束了。浅墨在这里提前祝大家圣诞节快乐~下周一,新的游戏编程征程,我们不见不散~&标签:原文地址:http://blog.csdn.net/poem_qianmo/article/details/
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!

我要回帖

更多关于 unity3d shader 的文章

 

随机推荐