附上一个学习Shader的好网站
OpenGL渲染管线
在OpenGL中,任何事物都在3D空间中,但是屏幕和窗口都是2D像素数组,所以大部分都是将3D坐标转化为适应屏幕的2D像素。
首先是要进行顶点着色器,计算顶点颜色将游戏物体的坐标转换成相机坐标。
然后要进行光栅化,将顶点转换成像素,使用片段着色器,计算每一个像素的最终颜色。
再通过alpha测试,模板测试,深度测试,获取需要绘制的像素,通过blend进行混合,再放入GBuffer缓存区等待渲染,
我们目前看到的显示屏上面的东西是叫framebuffer,称为正在显示的像素,然后有个叫frontBuffer是下一帧所渲染的东西,framebuffer之后就是frontBuffer。
什么是Shader
是一种可编程的渲染管线,也就是代码- -
固定渲染管线测试
//Shader能渲染出什么是和显卡有关系的 Shader "Unlit/Test01" //类的Class,类名路径 { Properties //定义的属性 { //名字,属性,默认值 _MainTex ("Texture", 2D) = "white" {} _TestInt("Int",Int) = 0 _TestFloat("Float",Float) = 1 _TestRange("Range",Range(0,1)) = 1 _TestColor("Color",Color) = (1,1,1,1) } SubShader //着色器,一个Shader可以包含多个着色器 { Tags { "RenderType"="Opaque" } LOD 100 //层级 Lighting On //打开光照 Material { Diffuse[_TestColor] //开启自发光 Ambient[_TestColor] //开启环境光 } Pass //渲染通道,具体计算渲染的东西,可以有多个pass,但是每个pass都会渲染一次,产生一次drawcall { SetTexture[_MainTex] //显示图片 { combine Texture * Previous } } } FallBack "Diffuse"//表示如果现在的shader不能够渲染出来,就返回到这个指定的shader中,直到找到合适的shader,可以无限套娃。 }
可编程渲染管线测试
Shader "Hidden/Test02" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { // No culling or depth Cull Off ZWrite Off ZTest Always Pass { CGPROGRAM #pragma vertex vert //顶点着色器 #pragma fragment frag //片元着色器 #include "UnityCG.cginc"//引用 struct appdata//由meshrender传入的 { float4 vertex : POSITION;//顶点信息 float2 uv : TEXCOORD0;//UV信息 }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v)//顶点着色器之后经过光栅化(光栅化不能进行修改),然后进入片元着色器 { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target//片元着色器操作 { fixed4 col = tex2D(_MainTex, i.uv); // just invert the colors // col.rgb = 1 - col.rgb; return col; } ENDCG } } }
Aplha测试
Shader "Hidden/Test03" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { // No culling or depth //Cull Off ZWrite Off ZTest Always Blend SrcAlpha OneMinusSrcAlpha //混合 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); if(col.a < 0.5) //透明的小于多少就直接剔除掉 { return fixed4(0,0,0,0); } // just invert the colors // col.rgb = 1 - col.rgb; return col; } ENDCG } } }
模板测试
Shader "Examples/CommandExample" { SubShader { // 仅当模板缓冲区的当前值小于 2 时,此子着色器中的所有像素才通过模板测试 // 如果希望仅绘制到渲染目标中未"遮罩"的区域,则通常会执行此操作 Stencil { Ref 2 Comp Less } // 此处是定义子着色器的代码的其余部分。 Pass { // 此处是定义通道的代码的其余部分。 } } }
深度测试
Cull Off //剔除 ZWrite On //写入深度缓存 ZTest Greater //深度大小
Blend
Blend SrcAlpha OneMinusSrcAlpha // 传统透明度 Blend One OneMinusSrcAlpha // 预乘透明度 Blend One One // 加法 Blend OneMinusDstColor One // 软加法 Blend DstColor Zero // 乘法 Blend DstColor SrcColor // 2x 乘法
这里是有hi地区,一位独立游戏业余开发者