Unity3d 基于物理渲染Physically-Based Rendering之最终篇

前情提要:

讲求基本算法

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。
[cpp]  view plain  copy
  1. 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发表的效果:

 


 

可惜我没有那么高大上的模型做实验,可惜了,就用人脸做代替

代码如下:

[cpp]  view plain  copy
  1. Shader "Custom/reflect new ops3" {    
  2.     Properties{    
  3.     _MainTex("Base (RGB)", 2D) = "white" {}    
  4.     _Maintint("Main Color", Color) = (1, 1, 1, 1)    
  5.         _Cubemap("CubeMap", CUBE) = ""{}    
  6.     _SC("Specular Color", Color) = (1, 1, 1, 1)    
  7.         _GL("gloss", Range(0, 1)) = 0.5    
  8.         _nMips("nMipsF", Range(0, 5)) = 0.5    
  9.         _ReflAmount("Reflection Amount", Range(0.01, 1)) = 0.5    
  10. }    
  11.     SubShader{    
  12.         pass{//平行光的的pass渲染    
  13.         Tags{ "LightMode" = "ForwardBase" }    
  14.         Cull Back    
  15.             CGPROGRAM    
  16. #pragma vertex vert    
  17. #pragma fragment frag    
  18. #include "UnityCG.cginc"    
  19.     
  20.             float4 _LightColor0;    
  21.         samplerCUBE _Cubemap;    
  22.         float4 _SC;    
  23.         float _GL;    
  24.         float4 _Maintint;    
  25.         float _nMips;    
  26.         float _ReflAmount;    
  27.         uniform sampler2D _MainTex;    
  28.         float4 _MainTex_ST;    
  29.         struct v2f {    
  30.             float4 pos : SV_POSITION;    
  31.             float2 uv_MainTex : TEXCOORD0;    
  32.             float3 lightDir : TEXCOORD1;    
  33.             float3 viewDir : TEXCOORD2;    
  34.             float3 normal : TEXCOORD3;    
  35.     
  36.         };    
  37.     
  38.         v2f vert(appdata_full v) {    
  39.             v2f o;    
  40.             o.pos = mul(UNITY_MATRIX_MVP, v.vertex);//切换到世界坐标    
  41.             o.normal = v.normal;    
  42.             o.lightDir = ObjSpaceLightDir(v.vertex);    
  43.             o.viewDir = ObjSpaceViewDir(v.vertex);    
  44.             o.uv_MainTex = TRANSFORM_TEX(v.texcoord, _MainTex);    
  45.             return o;    
  46.         }    
  47. #define PIE 3.1415926535        
  48.     
  49.     
  50.         float4 frag(v2f i) :COLOR    
  51.         {    
  52.             float3 viewDir = normalize(i.viewDir);    
  53.             float3 lightDir = normalize(i.lightDir);    
  54.             float3 H = normalize(lightDir + viewDir);    
  55.             float3 N = normalize(i.normal);    
  56.             float _SP = pow(8192, _GL);    
  57.             float d = (_SP + 2) / (8 * PIE) * pow(dot(N, H), _SP);    
  58.             //  float f = _SC + (1 - _SC)*pow((1 - dot(H, lightDir)), 5);    
  59.             float f = _SC + (1 - _SC)*pow(2, -10 * dot(H, lightDir));    
  60.             float k = min(1, _GL + 0.545);    
  61.             float v = 1 / (k* dot(viewDir, H)*dot(viewDir, H) + (1 - k));    
  62.     
  63.                 float all = d*f*v;    
  64.             //  float3 refDir = N - lightDir / 2;//H    
  65.                 float3 refDir = reflect(-viewDir,N);    
  66.                 float3 ref = texCUBElod(_Cubemap, float4(refDir, _nMips - _GL*_nMips)).rgb;//* _ReflAmount;    
  67.             float3 c = tex2D(_MainTex, i.uv_MainTex);    
  68.             float3 diff = dot(lightDir, N);    
  69.         //  diff /= PIE;    
  70.             diff = (1 - all)*diff;    
  71.     
  72.         //  return float4(c *(diff + all), 1)  * _LightColor0;    
  73.             return float4(lerp(c, ref, _ReflAmount) *(diff*_Maintint + all), 1)*_LightColor0;    
  74.         //  return float4(ref*((_Maintint+0.2) * (1 - dot(lightDir, N))) + c *(diff*_Maintint + all), 1)*_LightColor0;    
  75.         //  return float4(lerp(c, ref, _ReflAmount) *(diff*(_Maintint + 0.2)* (1 - dot(lightDir, N)) + all), 1)*_LightColor0;    
  76.         }    
  77.         ENDCG    
  78.     }    
  79.     }    
  80. }    



                                       ----- by wolf96  http://blog.csdn.net/wolf96
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值