shader总结一

mesh filter:存储一个mesh网格,来支撑这个物体的轮廓
mesh render:根据物体样子给予皮肤和颜色
OpenGL和
DirectX:提供了渲染图形的许多接口,让处理更加简化


shader:一种渲染命令,由OpenGL和directX进行解析,来控制渲染各种图形

GLSL shader语言用于OpenGL

HLSL shader语言用于directX

英伟达CG编写shader可以在OpenGL和directX通用


Unity Shader的分类:

使用的是ShaderLab编写unity中的的shader

1 表面着色器 Surface Shader

2 顶点/片元着色器 Vertex/Fragment Shader

3 固定函数着色器 Fixed Function Shader 


在unity中创建一个shader用vs编写:Shader "myShader"{   } 这里“”表示shader的名字,如果“siki/myshader”表示siki栏下面名为myshader。



如果只写了一个空shader那么unity不知道如何渲染,调用shader就会显示出紫色

在myshader{}中第一个是属性Properties{   }



                                  

这些属性中Range是对数进行限制,默认为6,  这里2D表示2D纹理,我们可以看到在inspector面板上显示出来了这些信息,我们可以在面板上修改这些属性,因此properties中的作用仅仅是在面板上显示出来这些属性




虽然在Properties中定义了但是在pass中要使用哪个还是再声明下,在属性中一行不加;在pass中要加分号

属性中color用了4个变量所以使用float4,当然使用float都可以用half或fiexed来代替。比如half4 _Color;

区别是使用float 用32位来存储用half使用16位存储从-6万到+6万,使用fixed使用11位存储,从-2到+2

shader中包含多个SubShader,但最少一个,unity会选用一个能够在目标平台上运行的subShader如果都不行,就使用Fallback语义指定的shader


每个图像都是由许多个三角面组成的,每个三角面由三个顶点组成

顶点函数:将顶点坐标从模型空间到剪裁空间的转换              格式:#pragma  vertex  vert

片元函数:确定每个像素的点的颜色                                          格式:#pragma  fragment  frag


结构体的定义:


这个a2v是自定义的名字,当传递多个数据的时候可以直接传递结构体


片元函数和顶点函数是如何传递数据的呢:

定义两个结构体v和f,在顶点函数参数传v返回f,在函数中变量赋值,在片元函数参数中传f进来



光照模型:是一个公式,使用这个公式可以计算某个点的光照效果

进入摄像机的光分为四类:

1 自发光

2 高光反射 specular

3 漫反射(diffuse)

4 环境光


渲染流水线的任务是:从一个3维场景出发,生成一个2维图像,由cpu和Gpu共同完成

渲染流程分为3个阶段:

应用阶段:准备场景数据,粗粒度剔除,输出渲染的几何信息,即渲染图元,在cpu上实现,这里又分为三个阶段,1,把数据加载到显存上,2,设置渲染状态。3,调用Draw Call

几何阶段:处理渲染图元,处理几何,在gpu上实现

光栅化阶段:渲染出最终图像,gpu上实现


渲染所需的数据会通过硬盘加载到内存中,网格纹理这些数据会又被加载到显存中,因为显卡对于显存的访问速度更快。

渲染状态:这些状态定义了场景中网格是怎样被渲染的,例如使用了那个顶点/片元着色器,光源属性,材质等

Draw Call:Cpu通过调用一个渲染命令来告诉Gpu,数据准备好,可以进行渲染,这个渲染命令就是Draw Call 



顶点着色器:实现顶点的空间变换,顶点着色                        曲面细分着色器:细分图元

裁剪:不在摄像机范围内的物体不需要被处理                        屏幕映射:把图元的x,y坐标转换到屏幕坐标系下

三角形设置:计算三角网格表示数据的过程                            片元着色器:


总结:如果问你3d流水线的流程或是渲染管线的工作原理?

答:渲染管线主要分为三个阶段:应用程序阶段、几何阶段、光栅阶段。应用程序阶段是Cpu和内存交互,顶点坐标、法向量、纹理坐标、纹理等数据作为源数据等待处理。几何阶段,负责顶点坐标变换、光照、裁剪、投影以及屏幕映射,gpu上实现。光栅化阶段,渲染出最终图像,gpu上实现。



1,cpu和gpu如何并行工作?

命令缓冲区包含一个命令队列,cpu添加命令,gpu读取


2,为什么Draw Call多了会影响帧率?

每次调用它之前,cpu需要检查渲染状态等,如果太多,cpu会把大量时间浪费在提交Draw Call上

3,如何减少Draw Call数量

批处理方法,把许多小的Draw Call合并成一个大的Draw Call,同时避免使用过多材质,尽量在不同网格之间只用同一材质


shader本身无法发生作用,必须和材质结合起来才能发生神奇的化学反应

shaderLab:自动封装了渲染的许多设置,让开发者编写shader更容易,也即编写shader的格式


世界空间:不解释

模型空间:局部空间,把世界空间看做模型空间的父空间系

模型变换(模型-世界变换)

模型变换的实质就是将模型上的顶点在模型空间中的描述,转换为在世界空间中的描述。假设有一个模型坐标系表示为矩阵 M(基于世界坐标系来描述),一个顶点在该模型坐标系上的坐标表示为列向量 D。 那么,该顶点在世界坐标系中的坐标 D‘,有如下变换关系:M·D = D’。M 也称为模型矩阵。模型矩阵本质上是一系列缩放、旋转和平移矩阵的复合矩阵。

视图空间

视图空间,也称为视点空间或摄像机空间或观察空间,从摄像机的角度来看,视图坐标系 x-轴和 y-轴的正方向分别指向摄像机右方和上方,而 z-轴的负方向则指向摄像机的镜头指向。

注意的是:观察空间和屏幕空间是不同的,从观察空间转到屏幕空间只需一个操作,就是投影

视图变换(世界-视图变换):将某个顶点在世界空间中的描述,转换为在视图空间中的描述。

模型视图矩阵(Model-View)

为了渲染一个模型,我们通常会先将它从模型空间变换到世界空间,然后再从世界空间变换到视图空间。这两个过程都有对应的变换矩阵:模型矩阵和视图矩阵。我们可以将这两个矩阵结合起来用一个复合矩阵来表示,这样的一个复合矩阵我们称为模型视图矩阵。通过模型视图矩阵,我们可以将模型上的顶点从模型空间直接变换到摄像机的视图空间

剪裁空间:
每个相机看到的场景不同,看到的保留,看不到的去除,叫做剪裁


屏幕空间:







漫反射代码:

在写shader的时候,出现的错误可能会在报错的那行的上面或者上上一行

漫反射的公式:

Shader "siki/myShader"{//两冒号是shader的名字

SubShader{
	Pass{
		Tags{"LightMode" = "ForwardBase" } //只有正确而定义了LightMode才能得到unity的内置光照变量
		CGPROGRAM
        #include "Lighting.cginc"  //包含unity的内置文件,才可以使用unity的内置变量
        #pragma vertex vert
        #pragma fragment frag

		struct a2v {
		float4 vertex : POSITION;//告诉unity把模型空间下的顶点坐标给vertex
		float3 normal:NORMAL; //取得法线
        };

	    struct v2f {
		float4 position:SV_POSITION;//把剪裁空间下的位置传给Position
		fixed3 color : COLOR;//用于接收最后的漫反射光的颜色
	    };
	 
	    v2f vert(a2v v) {  //把结构体a2v传进来,v2f传出去
		v2f f;
		f.position = mul(UNITY_MATRIX_MVP,v.vertex);//mul()是计算两个矩阵和向量相乘,UNITY_MATRIX_MVP矩阵是把顶点坐标从模型空间转换到剪裁空间
		fixed3 normalDir = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
		//由于拿到的法线是世界坐标下的,所以要转到模型空间下,通过mul相乘,由于World2Object是世界空间转模型空间矩阵,所以要想从模型空间转世界,把
		//两个参数互选下位置,由于矩阵是4x4,normal是float3所以要把矩阵强转为3x3,normalize是将向量单位化
		fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz); //平行光,所以光的位置就是光的方向
		fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir,lightDir),0);
		//这里_LightColor0是取得平行光的颜色,dot是两个向量点积
		f.color = diffuse;
			return f;
	}
    	fixed4 frag(v2f f): SV_Target {
		return fixed4(f.color,1);   //由于拿到的颜色是float3,所以最后一位在加上一个1
	}
    ENDCG
		  }
	}
		Fallback "VertexLit"  
}

高光反射的公式:specular=直射光*pow(max(cos夹角,0),10)   夹角等于反射光的方向和相机和物体之间的连线方向的夹角

通过max(cos夹角,0)取正数,通过pow(,10)来将它乘以10次幂将曲线的陡度提起来

高光反射的效果:可以看到球体的上头有个亮点,这个亮点会随着视角的移动而移动,这就是高光反射


Lambert模型较好的表现了粗糙表面的光照现象,如墙壁,纸张等,但是在用于诸如金属等有光泽效果的材质上则会显得呆板,表现不出光泽,主要原因是Lambert光照模型没有考虑表现这些表面的镜面反射效果。
一个光滑物体被光照射时,可以从某个方向上看到很强的反射光,这是因为在接近镜面反射角的一个区域内,反射了入射光的全部或大部分光强,这种现象称为镜面发射。也可以理解为高光反射
故此,提出一个计算镜面反射光强的光照模型,称为Phong模型,认为镜面反射的光强与反射光线和视线的夹角相关。

BlinnPhong光照模型混合和了Lambert的漫反射和标准的高光,渲染有时比Phong高光更柔和、更平滑,此外它的处理速度相当快,因此成为许多CG软件中默认的光照渲染方法


上面的代码用到的一些系统函数:



写代码的时候要想把多行向右移动,选中代码,按Tab键即可



  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值