次表面反射二
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如下:
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
在上面文章的基础上摄像机代码做如下修改:
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
相关文章推荐
- Cg Programming/Unity/Reflecting Surfaces反射表面
- Q132:PBRT-V3,BSSRDF(双向散射表面反射分布函数)(5.6.2章节、11.4章节)
- 反射执行带泛型的方法
- 反射基础
- java反射和内省
- Atitit.跨语言反射api 兼容性提升与增强 java c#。Net php js
- 反射 运用
- asp.net mvc 反射应用
- java反射详解(转)
- 【Java】反射之Class.forName()
- Cedar老师的java中的反射学习笔记(二)--动态加载
- java反射、内省、注解
- flex 反射
- 黑马程序员-Java高新技术之反射
- C#通过反射让Request对象只读属性可写的方法
- VB.NET机房收费系统之配置文件+反射
- 数组的反射
- Android通过反射实现强制停止应用程序的方法
- 【转】java的反射机制中的动态代理代理(二)--在远程方法调用中运用代理类
- java反射(1) 之class.forName(""), 类名.class, 对象.getClass()区别