您的位置:首页 > 移动开发 > Unity3D

次表面反射二

2017-07-14 14:33 113 查看
使用摄像机计算物体的厚度,薄的地方透光率高,后的地方透光率低,首先需要一个shader去计算物体背面的深度,然后在渲染物体表面的时候,两者做差值即可得出物体的厚度。

在上面文章的基础上摄像机代码做如下修改:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DepthTest1 : MonoBehaviour
{
public Shader depthShader;
public Material mt;
public RenderTexture m_depthTexture;
private Camera camereDepth;

// Use this for initialization
void Start ()
{
m_depthTexture = new RenderTexture ((int)Camera.main.pixelWidth, (int)Camera.main.pixelHeight, 24);
m_depthTexture.hideFlags = HideFlags.DontSave;
GameObject go = new GameObject ("camereDepth");
camereDepth = go.AddComponent<Camera> ();
camereDepth.CopyFrom (Camera.main);
camereDepth.enabled = false;
}

// Update is called once per frame
void OnPreRender ()
{
if (null != depthShader) {
camereDepth.targetTexture = m_depthTexture;
camereDepth.RenderWithShader (depthShader, "");
mt.SetTexture ("_BackDepthTex", m_depthTexture);
}
}
}


存储深度的shader,需要存储的是物体的背面,所以要使用指令CULL FRONT,代码如下
Shader "Unlit/RenderBackDepth"
{
SubShader
{
Tags { "RenderType"="Opaque"}

Pass
{
cull front
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"

struct appdata
{
float4 vertex : POSITION;
float3 normal:NORMAL;
};

struct v2f
{
float4 vertex : SV_POSITION;
float2 depth:TEXCOORD0;
};

v2f vert (appdata v)
{
v2f o;
v.vertex.xyz+=v.normal*0.005;//去除白边
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.depth = o.vertex.zw;
return o;
}

float4 frag (v2f i) : SV_Target
{
return EncodeFloatRGBA(i.depth.x/i.depth.y);
}
ENDCG
}
}
}

渲染物体的shader如下:

Shader "Custom/wrap_diff"
{
Properties {
_Diffuse("Diffuse", Color) = (1, 1, 1, 1)
_Specular("Specular",Color)=(1.0,1.0,1.0,1.0)
_Shinness("Shinness",Range(8,256))=128
_Wrap("Wrap",Range(0,1))=0.5
_ScatterWidth("_ScatterWidth",Vector)=(0,0,0,0)
_ScatterFactor("_ScatterFactor",Range(0,1))=0.75
_MainTex("MainTex",2D)="white"{}
_ScatterTex("_ScatterTex",2D)="white"{}
}

SubShader {
Tags { "RenderType"="Opaque" "Queue"="Geometry"}
Pass{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "Lighting.cginc"

fixed4 _Diffuse;
float _Wrap;
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _ScatterWidth;
float _ScatterFactor;
sampler2D _ScatterTex;
float4 _ScatterTex_ST;
float4 _Specular;
float _Shinness;
sampler2D _BackDepthTex;
float4x4 _WolrdtoLightMatrix;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 tangent:TANGENT;
float2 texcoord:TEXCOORD0;
};

struct v2f {
float4 pos : SV_POSITION;
float3 wNormal : TEXCOORD0;
float4 wPos:TEXCOORD1;
float4 uv:TEXCOORD2;
float4 scrPos:TEXCOORD3;
};

v2f vert(a2v v) {
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.wNormal = mul(v.normal, (float3x3)unity_WorldToObject);
o.scrPos = ComputeScreenPos(o.pos);
o.wPos = mul(unity_ObjectToWorld,v.vertex);
o.uv.xy = TRANSFORM_TEX(v.texcoord,_MainTex);
o.uv.zw = TRANSFORM_TEX(v.texcoord,_ScatterTex);

return o;
}

fixed4 frag(v2f i) : SV_Target {
float frontDepth = LinearEyeDepth( i.scrPos.z/i.scrPos.w );
float4 backDepthColor = tex2D(_BackDepthTex, i.scrPos.xy/i.scrPos.w);
float backDepth = LinearEyeDepth(DecodeFloatRGBA(backDepthColor));
float depth = backDepth-frontDepth;
float3 scattering = exp(-_ScatterWidth.xyz*depth);

float3 N =normalize(i.wNormal);

float4 texcol = tex2D(_MainTex, i.uv.xy);
fixed3 albedo = texcol.rgb*_Diffuse.rgb;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
float3 L = normalize(UnityWorldSpaceLightDir(i.wPos));
float3 V= normalize(UnityWorldSpaceViewDir(i.wPos));
float3 H = normalize(L+V);

float wrap = (dot(L,N)+_Wrap)/(1+_Wrap);
float wrap_diff = max(0,wrap);
fixed3 diffuse = _LightColor0.rgb * wrap_diff*albedo;

float s = pow(max(0,dot(N,H)),_Shinness);
float3 specular = _LightColor0.rgb *_Specular.rgb*s;

float3 scatterTex = tex2D(_ScatterTex,i.uv.zw);

float4 finCol = float4(0,0,0,0);

finCol.rgb =lerp(ambient+diffuse,scattering*scatterTex,_ScatterFactor)+specular;
finCol.a = texcol.a;

return finCol;
}

ENDCG
}
}
// FallBack "Diffuse"
}


最后就得到我们想要的效果了:



参考文章:
http://gad.qq.com/article/detail/7159485?ADTAG=gad.cx.tb
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  次表面散射 unity SSS