前情提要:
讲求基本算法
Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF
plus篇
Unity3d 基于物理渲染Physically-Based Rendering之实现
最后我们用fragment shader 实现,加上diffuse漫反射,代码和之前的surface差不多,只是多了reflect方向的计算,reflect方向的计算方法为用CG函数库中函数reflect,
float3 reflect(float3 i, float3 n);
i为in入射方向,n为normal发现方向,此处入射方向为view direction。
- float3 refDir = reflect(-viewDir,N);
参考了下SIGGRAPH 2013中虚幻引擎的diffuse
他们的方法为new diffuse = diffuse color/π。
把π改为可控参数就好,调成我们想要的效果。
建立了一个外部变量_ReflAmount为cubeMap和diffuse的比重,_ReflAmount越高反射周围景物越明显
这是本文实现效果
_ReflAmount = 0.5
_ReflAmount = 0
有没有要滴出血的感觉?
_ReflAmount = 1
高大上的丝袜黑
_ReflAmount = 1
_ReflAmount = 0
_ReflAmount = 0.5
与unity作比较:
diffuse:
specular:
这是虚幻引擎在SIGGRAPH 2013发表的效果:
可惜我没有那么高大上的模型做实验,可惜了,就用人脸做代替
代码如下:
- Shader "Custom/reflect new ops3" {
- Properties{
- _MainTex("Base (RGB)", 2D) = "white" {}
- _Maintint("Main Color", Color) = (1, 1, 1, 1)
- _Cubemap("CubeMap", CUBE) = ""{}
- _SC("Specular Color", Color) = (1, 1, 1, 1)
- _GL("gloss", Range(0, 1)) = 0.5
- _nMips("nMipsF", Range(0, 5)) = 0.5
- _ReflAmount("Reflection Amount", Range(0.01, 1)) = 0.5
- }
- SubShader{
- pass{
- Tags{ "LightMode" = "ForwardBase" }
- Cull Back
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
-
- float4 _LightColor0;
- samplerCUBE _Cubemap;
- float4 _SC;
- float _GL;
- float4 _Maintint;
- float _nMips;
- float _ReflAmount;
- uniform sampler2D _MainTex;
- float4 _MainTex_ST;
- struct v2f {
- float4 pos : SV_POSITION;
- float2 uv_MainTex : TEXCOORD0;
- float3 lightDir : TEXCOORD1;
- float3 viewDir : TEXCOORD2;
- float3 normal : TEXCOORD3;
-
- };
-
- v2f vert(appdata_full v) {
- v2f o;
- o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
- o.normal = v.normal;
- o.lightDir = ObjSpaceLightDir(v.vertex);
- o.viewDir = ObjSpaceViewDir(v.vertex);
- o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);
- return o;
- }
- #define PIE 3.1415926535
-
-
- float4 frag(v2f i) :COLOR
- {
- float3 viewDir = normalize(i.viewDir);
- float3 lightDir = normalize(i.lightDir);
- float3 H = normalize(lightDir + viewDir);
- float3 N = normalize(i.normal);
- float _SP = pow(8192, _GL);
- float d = (_SP + 2) / (8 * PIE) * pow(dot(N, H), _SP);
-
- float f = _SC + (1 - _SC)*pow(2, -10 * dot(H, lightDir));
- float k = min(1, _GL + 0.545);
- float v = 1 / (k* dot(viewDir, H)*dot(viewDir, H) + (1 - k));
-
- float all = d*f*v;
-
- float3 refDir = reflect(-viewDir,N);
- float3 ref = texCUBElod(_Cubemap, float4(refDir, _nMips - _GL*_nMips)).rgb;
- float3 c = tex2D(_MainTex, i.uv_MainTex);
- float3 diff = dot(lightDir, N);
-
- diff = (1 - all)*diff;
-
-
- return float4(lerp(c, ref, _ReflAmount) *(diff*_Maintint + all), 1)*_LightColor0;
-
-
- }
- ENDCG
- }
- }
- }
----- by wolf96 http://blog.csdn.net/wolf96