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。

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{//平行光的的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((1 - dot(H, lightDir)), 5);
			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 = N - lightDir / 2;//H
				float3 refDir = reflect(-viewDir,N);
				float3 ref = texCUBElod(_Cubemap, float4(refDir, _nMips - _GL*_nMips)).rgb;//* _ReflAmount;
			float3 c = tex2D(_MainTex, i.uv_MainTex);
			float3 diff = dot(lightDir, N);
		//	diff /= PIE;
			diff = (1 - all)*diff;

		//	return float4(c *(diff + all), 1)  * _LightColor0;
			return float4(lerp(c, ref, _ReflAmount) *(diff*_Maintint + all), 1)*_LightColor0;
		//	return float4(ref*((_Maintint+0.2) * (1 - dot(lightDir, N))) + c *(diff*_Maintint + all), 1)*_LightColor0;
		//	return float4(lerp(c, ref, _ReflAmount) *(diff*(_Maintint + 0.2)* (1 - dot(lightDir, N)) + all), 1)*_LightColor0;
		}
		ENDCG
	}
	}
}

                                       ----- by wolf96


posted @ 2015-03-11 19:14  战狼96  阅读(3230)  评论(0编辑  收藏  举报