shader总结三

来源:互联网 发布:全景图拼接软件 编辑:程序博客网 时间:2024/06/04 00:27

切线空间下的法线贴图做法步骤:

1,

最后面的bump是使用模型自带的法线贴图

2,那么法线贴图也需要一个uv坐标(纹理坐标),一个物体本身的贴图一个法线贴图


3,在struct中虽然不需要用法线和切线但是依然要定义一个法线和切线,因为切线空间的切线是和法线垂直的,切线空间是通过切线和法线共同确定的

用一个float4,它的xy保存贴图的纹理坐标,zw保存法线贴图的纹理坐标,通过法线贴图的纹理坐标来获取法线贴图的颜色值

在vert函数中


4,把所有跟法线方向有关的运算都放在切线空间下

在片元函数中,先通过tex2D获取法线贴图的颜色,通过得到像素转法线的映射


而在下面的代码中是通过来将法线映射到切线空间下的

5,把光的方向转成切线空间,每个顶点的切线空间是不一样的,是有每个点的法线和切线来确定的,那么要通过顶点函数来处理,用

来作为临时变量在顶点函数中保存下来传递给片元函数


完整代码:




就得到了有凹凸效果的物体:


让贴图效果更加凹凸的做法:更改tangentNormal.xy即可,效果


最后注意的是tangent类型是float4而不是float3,原因是tangent.w分量来决定切线空间下的第三个坐标轴


渲染顺序:在一幅图像上,哪个物体先渲染,哪个后渲染是顺序是不一样的,所以在必要的情况下要在tag里面指定Queue的渲染队列,对于要把物体弄成透明的时候就要指定Queue


[FallBack]意思是当shader有多种方案时,保证能有一种方案能运行


什么是shader:


什么是渲染管线:


Shader的三种编程语言:
1,基于OpenGL的,简称GLSL
2,基于DirectX的,简称HLSL
3,英伟达公司的CG语言
HLSL和CG其实是同一种语言,学CG语言的好处,能被GLSL和HLSL都支持

Unity3D编写shader有三种方式:
1,fixed function shader (固定功能着色器)
最简单的着色器类型,只能使用Unity3D自带的固定语法和提供的方法,适用于任何硬件,使用难度最小
,2,vertex and fragment shader (顶点片段程序着色器)
顶点片段着色器,效果最为丰富的着色器类型,使用Cg/HLSL语言规范,着色器由顶点程序和片段程序组成。所有效果都需要自己编写,使用难度相对较大。
3,surface shader (表面着色器)
同样使用Cg/HLSL语言规范的着色器类型,不过把光照模型提取出来,可以使用Unity3D自带的一些光照模型,也可以自己编写光照模型,着色器同样由顶点程序和片段程序组成,不过本身有默认的程序方法,使用者可以只针对自己关系的效果部分进行编写。由于选择性比较大,所以可以编写出较为丰富的效果,使用难度相对vertex and fragment shader小。

1、Fixed Function shaders代码实例
Shader "VertexLit" {    Properties {                                                              //在unity材质面板上的属性        _Color ("Main Color", Color) = (1,1,1,0.5)        _SpecColor ("Spec Color", Color) = (1,1,1,1)        _Emission ("Emmisive Color", Color) = (0,0,0,0)        _Shininess ("Shininess", Range (0.01, 1)) = 0.7        _MainTex ("Base (RGB)", 2D) = "white" { }                    //在面板上添加一个材质属性    }    SubShader {        Pass {            Material {                Diffuse [_Color]                          //在material中更改Diffuse漫反射的效果,括号里面是通过调用面板里面的参数                Ambient [_Color]                 //意思是更改面板的参数来更改漫反射,高光反射等等的效果                Shininess [_Shininess]           //这个Shininess是显示高光反射的区域                Specular [_SpecColor]                Emission [_Emission]            }            Lighting On                          //必须要把Lighting on打开,否则unity中物体是全黑的            SeparateSpecular On                  //要使用高光反射的时候使用Specular就要加上这句话把它打开            SetTexture [_MainTex] {               //为物体添加上材质                constantColor [_Color]                Combine texture * primary DOUBLE, texture * constant     //注意的是添加材质后还有将material中的多种光源混合起来所以*primary            }                //DOUBLE意思是乘以2倍的光源亮度,看起来更亮,逗号第二个参数是修改Alfha的        }    }} 


如果添加了2张纹理,那么第二张的纹理颜色值要乘以第一张的和material中的光源的叠加,所以*previous


2、Surface shaders代码实例

3、CG代码实例


frag返回的是fixed4的数,但是还不够,还要说明返回的是什么类型,所有后面加上:COLOR

inout表示即输入又输出


uniform关键字,表示后面的这个值要由unity来给它提供


然后写一个脚本获取Renderer组件来设置,把脚本拖动到物体上


MVP中V是View即相机空间的意思


这是怎么实现的?


首先程序不能是静止的要是运行的,调用sin,cos的时间函数,改变的是一点的值,但是这里周围的颜色是做了插值运算,所以这样了,/2+0.5是把(-1,1)范围改成(0,1)


光带效果是怎么实现的?(下文仅是通过顶点函数来实现也可使用其他方式,在顶点里面处理很消耗性能)


在shader中顶点函数,要取得屏幕的x和y,先通过mvp把模型空间顶点转成剪裁空间下,x除以它的第四个分量w得到屏幕里的x和y,因为红色带就是在x某个范围内颜色为红,否则白色,x的左边和右边是移动的,所以dis用脚本的Time.deltaTime取得


再写一个脚本,挂到物体上,修改shader里面的变量



让一个平面凸起来怎么实现?

在模型空间下找到x和y距离0,0点的距离,这里用x,z轴构成的平面表示xy,取原点为圆心长度为1内的圆,圆心处d为1,圆外为0,把d乘以平面的z的值(这里y轴表示z轴)把该点转换到屏幕空间中


如果把颜色设成这样


效果就成这样


这样效果如何实现?


距离原点越远的地方旋转越大,构造旋转矩阵m,绕y轴旋转,旋转矩阵cos和sin的角度取自顶点距离圆心的距离乘以sinTime.w,从模型空间转到剪裁空间,剪裁空间下的旋转矩阵乘以模型空间下的顶点(为什么两个不放在同一空间相乘呢)




这样的效果如何实现?


其他代码不变,更改旋转矩阵变为缩放矩阵。只对x轴进行缩放


发现效果如下


这说明x轴的缩放太大了,我们要控制缩放的范围,改成sin(angle)/8+0.5,  效果如下


注意的是,它的波动是周期的,变成非周期的,就把sin去掉,直接Time.y,把顶点到原点的length改成蓝色轴的值比较好


效果就是最上面的那种

试想一下,如果构造如下的矩阵相乘后有效果吗?


答:没效果,因为该物体是个平面物体,黄轴也即y轴为0,因此如果一个平面物体让它上下运动就不能通过矩阵的形式乘了,改成点相乘


对于代码的执行效率优化:矩阵相乘有许多0相乘没必要算,那么把矩阵相乘直接改成有值的点和点的相乘,去除没必要的点


这种效果怎么实现?



思想,一个点在上下做周期运动,同时该点颜色也是周期变动,所以都是sin函数

如果要变成圆形抖动,就要把v.vertex.z改成length(v.vertex.xz)


如果改成这样


效果这样:



素材取自蛮牛教育

原创粉丝点击