【OpenGL】Shader实例分析-钻石效果
发表于2018-10-18
最近研究了一个玻璃折射的效果(用在钻石上),虽然没有达到最满意的效果,还是先分享出来,待以后有更好的想法再补充。
先看效果吧:
这里面有两个效果,左边是unity的免费插件Gem Shader,右边的是我自己实现的,我将分别介绍这两个效果的实现方法。
一、知识补充:
钻石的图片:
两个shader都使用了CubeMap……
Shader "FX/Diamond" { Properties { _Color ("Color", Color) = (1,1,1,1) _ReflectTex ("Reflection Texture", Cube) = "dummy.jpg" { TexGen CubeReflect } _RefractTex ("Refraction Texture", Cube) = "dummy.jpg" { TexGen CubeReflect } } SubShader { Tags { "Queue" = "Transparent" } // First pass - here we render the backfaces of the diamonds. Since those diamonds are more-or-less // convex objects, this is effectively rendering the inside of them Pass { Color (0,0,0,0) Offset -1, -1 Cull Front ZWrite Off SetTexture [_RefractTex] { constantColor [_Color] combine texture * constant, primary } SetTexture [_ReflectTex] { combine previous, previous +- texture } } // Second pass - here we render the front faces of the diamonds. Pass { Fog { Color (0,0,0,0)} ZWrite on Blend One One SetTexture [_RefractTex] { constantColor [_Color] combine texture * constant } SetTexture [_ReflectTex] { combine texture + previous, previous +- texture } } } // Older cards. Here we remove the bright specular highlight SubShader { // First pass - here we render the backfaces of the diamonds. Since those diamonds are more-or-less // convex objects, this is effectively rendering the inside of them Pass { Color (0,0,0,0) Cull Front SetTexture [_RefractTex] { constantColor [_Color] combine texture * constant, primary } } // Second pass - here we render the front faces of the diamonds. Pass { Fog { Color (0,0,0,0)} ZWrite off Blend One One SetTexture [_RefractTex] { constantColor [_Color] combine texture * constant } } } // Ancient cards without cubemapping support // We could use a 2D refletction texture, but the chances of getting one of these cards are slim, so we won't bother. SubShader { Pass { Color [_Color] } } }
Shader "stalendp/myDiamondShader" { Properties { _Color ("Color", Color) = (1,1,1,1) _ReflectTex ("Reflection Texture", Cube) = "" { } _RefractTex ("Refraction Texture", Cube) = "" { } } CGINCLUDE #include "UnityCG.cginc" fixed4 _Color; samplerCUBE _RefractTex; samplerCUBE _ReflectTex; struct v2f { half4 pos:SV_POSITION; half3 Reflect : TEXCOORD0; half3 RefractR : TEXCOORD1; half3 RefractG : TEXCOORD2; half3 RefractB : TEXCOORD3; half Ratio : TEXCOORD4; }; v2f vert(appdata_full v) { float EtaR = 0.65; float EtaG = 0.67; float EtaB = 0.69; float FresnelPower = 5.0; float F = ((1.0-EtaG) * (1.0-EtaG)) / ((1.0+EtaG) * (1.0+EtaG)); float3 i = -normalize(ObjSpaceViewDir(v.vertex)); float3 n = normalize(v.normal); // ?????? v2f o; o.Ratio = F + (1.0 - F) * pow((1.0 - dot(-i, n)), FresnelPower) ; o.RefractR = refract(i, n, EtaR); o.RefractG = refract(i, n, EtaG); o.RefractB = refract(i, n, EtaB); o.Reflect = reflect(i, n); o.pos = mul (UNITY_MATRIX_MVP, v.vertex); return o; } fixed4 frag(v2f i) : COLOR0 { float3 refractColor, reflectColor; refractColor.r = float3(texCUBE(_RefractTex, i.RefractR)).r; refractColor.g = float3(texCUBE(_RefractTex, i.RefractG)).g; refractColor.b = float3(texCUBE(_RefractTex, i.RefractB)).b; reflectColor = float3(texCUBE(_ReflectTex, i.Reflect)); return 2*_Color * pow(fixed4(lerp( _Color * refractColor * 5, reflectColor * 2, i.Ratio), 1), 1.8); } ENDCG SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma fragmentoption ARB_precision_hint_fastest ENDCG } } FallBack Off }
来自:https://blog.csdn.net/stalendp/article/details/46360409