Unity Shader之色彩变换-腾讯游戏学院
source link: http://gad.qq.com/article/detail/287447
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
渲染管线
一般分为固定渲染管线和可编程渲染管线。固定管线因为功能固定,无法在程序上对物体细节的表现给予更多更自由的控制,无法达到更多更炫酷的效果。为了解决这个问题,可编程的渲染管线就诞生了,见下图:
具体的可编程的部分就是上图中两个橙色的节点:Vertex Shader(顶点着色)和 Fragment Shader(片元着色)。
了解了Shader在渲染管线中的工作位置,那么我们在看看Unity中如何进行Shader开发呢?
Unity3D Shader
Unity的Shader有四种:
Fixed function shader
属于固定渲染管线Shader, 基本用于高级Shader在老显卡无法显示时的备用Shader。Vertex and Fragment Shader
最强大的Shader类型,属于可编程渲染管线。使用的是CG/HLSL语言。也就是我上面说过的两种。Surface Shader
Unity3d推荐的Shader类型。它是一个代码生成器,帮我们将重复的代码省去了,使得编写Shader更为容易。使用的也是CG/HLSL语言。Compute Shader
可直接将GPU作为并行处理器加以利用,GPU将不仅具有3D渲染能力,也具有其他的运算能力。
色彩是人的眼睛对于不同频率的光线的不同感受,色彩既是客观存在的(不同频率的光)又是主观感知的,有认识差异。计算机领域应用最多的是RGB,尤其是程序中处理。但是美术处理和工业应用领域应用更多的是HSV或HSL(举个大家最熟悉的例子:打开电视里面的色彩设置就会看到色相,饱和度,明亮度的设置)。
RGB(Red,Green,Blue)
就是红绿蓝组成的三维坐标系:
HSV(Hue色相,Saturation饱和度,Value色调)
由色相,饱和度,色调组成的倒立的圆锥体:
HSL(Hue色相,Saturation饱和度,Lightness亮度)
HSL 类似于 HSV。对于一些人,HSL 更好的反映了“饱和度”和“亮度”作为两个独立参数的直觉观念,但是对于另一些人,它的饱和度定义是错误的,因为非常柔和的几乎白色的颜色在 HSL 可以被定义为是完全饱和的。对于 HSV 还是 HSL 更适合于人类用户界面是有争议的(这个不在本文的讨论范围内,就不在深入了)。
HSV和HSL的对比图:
色彩相关的概念介绍完毕,下面在Unity中新建一个Shader
Shader "Custom/HSLShader" { Properties { _MainTex ("Texture", 2D) = "white" {} _DH("Hue",Range(0,360)) = 0 _DS("Saturation",Range(-1,1)) = 0 _DL("Lightness",Range(-1,1)) = 0 } SubShader { // No culling or depth // Cull Off ZWrite Off ZTest Always 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; }; sampler2D _MainTex; float _DH; float _DS; float _DL; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); float r = col.r; float g = col.g; float b = col.b; float a = col.a; float h; float s; float l; float maxv = max(max(r,g),b); float minv = min(min(r,g),b); if (maxv == minv){ h = 0.0; } else if (maxv == r && g >= b){ h = 60.0*(g-b)/(maxv-minv)+0.0; } else if (maxv == r && g < b ){ h = 60.0*(g-b)/(maxv-minv)+360.0; } else if (maxv == g){ h = 60.0*(b-r)/(maxv-minv)+120.0; } else if (maxv == b){ h = 60.0*(r-g)/(maxv-minv)+240.0; } l = 0.5*(maxv+minv); if (l == 0.0 || maxv == minv){ s = 0.0; } else if (0.0 <= l && l <= 0.5){ s = (maxv-minv)/(2.0*l); } else if (l > 0.5){ s = (maxv-minv)/(2.0-2.0*l); } h = h + _DH; s = min(1.0,max(0.0,s+_DS)); l = l + _DL; // final color float q; if (l < 0.5){ q = l*(1.0+s); }else if (l >= 0.5){ q = l+s-l*s; } float p = 2.0*l-q; float hk = h/360.0; float t[3]; t[0] = hk+1.0/3.0; t[1] = hk; t[2] = hk-1.0/3.0; for(int i=0;i<3;i++){ if (t[i] < 0.0){ t[i] += 1.0; }else if (t[i] > 1.0){ t[i] -= 1.0; } } float c[3]; for (int i=0;i<3;i++){ if (t[i] < 1.0/6.0){ c[i] = p+((q-p)*6.0*t[i]); }else if (1.0/6.0 <= t[i] && t[i] < 0.5){ c[i] = q; }else if (0.5 <= t[i] && t[i] < 2.0/3.0){ c[i] = p+((q-p)*6.0*(2.0/3.0-t[i])); }else{ c[i] = p; } } fixed4 finalColor = fixed4(c[0],c[1],c[2],a); finalColor += fixed4(_DL,_DL,_DL,0.0); return finalColor; } ENDCG } } }
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK