Unity3d 镜面反射

网上能找到的基本上是固定管道或表面渲染的shader。

特此翻译为顶点、片段渲染的Shader,

本源代码仅仅涉及shader与cs部分。

Editor部分使用NGUI绘制的,

请自行下载NGUI

unity3d 版本号:v4.3.1

ReflectionMirror.cs

using UnityEngine;
using System.Collections;
using System; /// <summary>
/// 反射效果
/// </summary>
[AddComponentMenu("GameCore/SpecialEffect/Reflection Mirror")]
[ExecuteInEditMode]
public class ReflectionMirror : MonoBehaviour
{
public bool DisablePixelLights = true;
public int TextureSize = 512;
public float ClipPlaneOffset = 0;
public LayerMask ReflectLayers = -1; private Hashtable m_ReflectionCameras = new Hashtable(); // Camera -> Camera table
private RenderTexture m_ReflectionTexture = null;
private int m_OldReflectionTextureSize = 0; private static bool s_InsideRendering = false; // This is called when it's known that the object will be rendered by some
// camera. We render reflections and do other updates here.
// Because the script executes in edit mode, reflections for the scene view
// camera will just work!
public void OnWillRenderObject()
{
if (!enabled || !renderer || !renderer.sharedMaterial || !renderer.enabled)
return; Camera cam = Camera.current;
if (!cam)
return; // Safeguard from recursive reflections.
if (s_InsideRendering)
return;
s_InsideRendering = true; Camera reflectionCamera;
CreateMirrorObjects(cam, out reflectionCamera); // find out the reflection plane: position and normal in world space
Vector3 pos = transform.position;
Vector3 normal = transform.up;
// Optionally disable pixel lights for reflection
int oldPixelLightCount = QualitySettings.pixelLightCount;
if (DisablePixelLights)
QualitySettings.pixelLightCount = 0; CoreTool.CloneCameraModes(cam, reflectionCamera); // Render reflection
// Reflect camera around reflection plane
float d = -Vector3.Dot(normal, pos) - ClipPlaneOffset;
Vector4 reflectionPlane = new Vector4(normal.x, normal.y, normal.z, d); Matrix4x4 reflection = CoreTool.CalculateReflectionMatrix(Matrix4x4.zero, reflectionPlane); Vector3 oldpos = cam.transform.position;
Vector3 newpos = reflection.MultiplyPoint(oldpos);
reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection; // Setup oblique projection matrix so that near plane is our reflection
// plane. This way we clip everything below/above it for free.
Vector4 clipPlane = CoreTool.CameraSpacePlane(reflectionCamera, pos, normal, 1.0f, ClipPlaneOffset); Matrix4x4 projection = cam.projectionMatrix; projection = CoreTool.CalculateObliqueMatrix(projection, clipPlane); reflectionCamera.projectionMatrix = projection; reflectionCamera.cullingMask = ~(1 << 4) & ReflectLayers.value; // never render water layer
reflectionCamera.targetTexture = m_ReflectionTexture; GL.SetRevertBackfacing(true);
reflectionCamera.transform.position = newpos;
Vector3 euler = cam.transform.eulerAngles;
reflectionCamera.transform.eulerAngles = new Vector3(0, euler.y, euler.z);
reflectionCamera.Render();
reflectionCamera.transform.position = oldpos;
GL.SetRevertBackfacing(false);
Material[] materials = renderer.sharedMaterials;
foreach (Material mat in materials)
{
if (mat.HasProperty("_ReflectionTex"))
mat.SetTexture("_ReflectionTex", m_ReflectionTexture);
} // Set matrix on the shader that transforms UVs from object space into screen
// space. We want to just project reflection texture on screen.
Matrix4x4 scaleOffset = Matrix4x4.TRS(
new Vector3(0.5f, 0.5f, 0.5f), Quaternion.identity, new Vector3(0.5f, 0.5f, 0.5f));
Vector3 scale = transform.lossyScale;
Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f / scale.x, 1.0f / scale.y, 1.0f / scale.z));
mtx = scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix * mtx;
foreach (Material mat in materials)
{
mat.SetMatrix("_ProjMatrix", mtx);
}
// Restore pixel light count
if (DisablePixelLights)
QualitySettings.pixelLightCount = oldPixelLightCount;
s_InsideRendering = false;
} // Cleanup all the objects we possibly have created
void OnDisable()
{
if (m_ReflectionTexture)
{
DestroyImmediate(m_ReflectionTexture);
m_ReflectionTexture = null;
}
foreach (DictionaryEntry kvp in m_ReflectionCameras)
DestroyImmediate(((Camera)kvp.Value).gameObject);
m_ReflectionCameras.Clear();
} // On-demand create any objects we need
private void CreateMirrorObjects(Camera currentCamera, out Camera reflectionCamera)
{
reflectionCamera = null; // Reflection render texture
if (!m_ReflectionTexture || m_OldReflectionTextureSize != TextureSize)
{
if (m_ReflectionTexture)
DestroyImmediate(m_ReflectionTexture);
m_ReflectionTexture = new RenderTexture(TextureSize, TextureSize,0);
m_ReflectionTexture.name = "__MirrorReflection" + GetInstanceID();
m_ReflectionTexture.isPowerOfTwo = true;
m_ReflectionTexture.hideFlags = HideFlags.DontSave;
m_ReflectionTexture.antiAliasing = 4;
m_ReflectionTexture.anisoLevel = 0;
m_OldReflectionTextureSize = TextureSize;
} // Camera for reflection
reflectionCamera = m_ReflectionCameras[currentCamera] as Camera;
if (!reflectionCamera) // catch both not-in-dictionary and in-dictionary-but-deleted-GO
{
GameObject go = new GameObject("Mirror Refl Camera id" + GetInstanceID() + " for " + currentCamera.GetInstanceID(), typeof(Camera), typeof(Skybox));
reflectionCamera = go.camera;
reflectionCamera.enabled = false;
reflectionCamera.transform.position = transform.position;
reflectionCamera.transform.rotation = transform.rotation;
reflectionCamera.gameObject.AddComponent("FlareLayer");
go.hideFlags = HideFlags.HideAndDontSave;
m_ReflectionCameras[currentCamera] = reflectionCamera;
}
}
}

ReflectionMirrorEditor.cs

using System.Collections;
using System;
using UnityEditor;
using UnityEngine;
/// <summary>
/// 反射效果
/// </summary>
[CustomEditor(typeof(ReflectionMirror))]
public class ReflectionMirrorEditor : Editor
{
string[] _renderTextureOptions = new string[8] { "16", "32", "64", "128", "256", "512", "1024", "2048" };
int _renderTextureWidthDefaultIndex = 5;
int _renderTextureWidthIndex = 5;
SerializedProperty _sp;
public override void OnInspectorGUI()
{
EditorGUILayout.HelpBox("This the reflection effect,it has mirror or sphere reflection!",MessageType.Info);
if (NGUIEditorTools.DrawHeader("Reflection Settings"))
{
NGUIEditorTools.BeginContents();
{
NGUIEditorTools.DrawProperty("Disable PixelLights", this.serializedObject, "DisablePixelLights");
NGUIEditorTools.DrawProperty("Reflect Layers", this.serializedObject, "ReflectLayers");
NGUIEditorTools.DrawProperty("ClipPlane Offset", this.serializedObject, "ClipPlaneOffset");
}
NGUIEditorTools.EndContents();
}
if (NGUIEditorTools.DrawHeader("Render Texture Settings"))
{
NGUIEditorTools.BeginContents();
{
_sp = this.serializedObject.FindProperty("TextureSize");
_renderTextureWidthIndex = GetTextureOptionsIndex(_sp.intValue.ToString());
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("TexSize:", GUILayout.Width(100));
_renderTextureWidthIndex = EditorGUILayout.Popup(_renderTextureWidthIndex, _renderTextureOptions);
EditorGUILayout.EndHorizontal(); if (GUILayout.Button("Make Default Value"))
{
_renderTextureWidthIndex = _renderTextureWidthDefaultIndex;
}
_sp.intValue = int.Parse(_renderTextureOptions[_renderTextureWidthIndex]);
}
NGUIEditorTools.EndContents();
} this.serializedObject.ApplyModifiedProperties();
} int GetTextureOptionsIndex(string value)
{
int index = 0;
for (int i = 0; i < _renderTextureOptions.Length; i++)
{
if (_renderTextureOptions[i].Equals(value, StringComparison.OrdinalIgnoreCase))
{
index = i;
}
}
return index;
}
}

Shader

Shader "GameCore/SpecialEffect/Reflection Mirror"
{
Properties {
_ReflectionTex ("Reflection", 2D) = "white" {TexGen ObjectLinear }
_ReflectionColor("Color",Color) = (1,1,1,1)
}
//PC
SubShader {
Tags {
"RenderType"="Opaque"}
LOD 100
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" uniform float4x4 _ProjMatrix;
uniform sampler2D _ReflectionTex;
float4 _ReflectionColor;
struct outvertex {
float4 pos : SV_POSITION;
float3 uv : TEXCOORD0;
};
outvertex vert(appdata_tan v) {
outvertex o;
o.pos = mul (UNITY_MATRIX_MVP,v.vertex);
float3 viewDir = ObjSpaceViewDir(v.vertex);
o.uv = mul(_ProjMatrix,float4(viewDir,0));
return o;
} float4 frag(outvertex i) : COLOR {
half4 reflcol = tex2Dproj(_ReflectionTex,i.uv);
return reflcol*_ReflectionColor;
}
ENDCG
}
}
//Mobile
SubShader {
Tags {
"RenderType"="Opaque"}
LOD 100
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" uniform float4x4 _ProjMatrix;
uniform sampler2D _ReflectionTex;
float4 _ReflectionColor;
struct outvertex {
float4 pos : SV_POSITION;
float3 uv : TEXCOORD0;
float4 posProj;
};
outvertex vert(appdata_tan v) {
outvertex o;
o.pos = mul (UNITY_MATRIX_MVP,v.vertex);
o.posProj = mul(_ProjMatrix, v.vertex);
return o;
}
float4 frag(outvertex i) : COLOR {
half4 reflcol = tex2D(_ReflectionTex,float2(i.posProj) / i.posProj.w);
return reflcol*_ReflectionColor;
}
ENDCG
}
}
}

来源链接: http://pan.baidu.com/s/1gdyzyNL

Unity3d 镜面反射 vertex and frag Shader源代码的更多相关文章

  1. Unity3d 镜面折射 vertex and frag Shader源代码

    Unity3d 镜面折射  网上能找到的基本上是固定管道或表面渲染的shader. 特此翻译为顶点.片段渲染的Shader, 本源代码仅仅涉及shader与cs部分, 请自行下载NGUI  unity ...

  2. unity3D 涂涂乐使用shader实现上色效果

    unity3D 涂涂乐使用shader实现上色效果 之前我博文里面发过一个简单的通过截图方式来实现的模型上色方法,但是那个方法不合适商用,因为你需要对的很准确才可以把贴图完美截取下来,只要你手抖了一下 ...

  3. UnityShader之顶点片段着色器Vertex and Fragment Shader【Shader资料】

    顶点片段着色器 V&F Shader:英文全称Vertex and Fragment Shader,最强大的Shader类型,也是我们在使用ShaderLab中的重点部分,属于可编程管线,使用 ...

  4. Vertex And Fragment Shader(顶点和片段着色器)

    Vertex And Fragment Shader(顶点和片段着色器) Shader "Unlit/ Vertex­_And_Fragment_Shader " { Proper ...

  5. Unity3D之高级渲染-Shader Forge增强版

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家.特邀编辑.畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  6. ShaderLab中vertex fragment类Shader基础格式笔记

    //U3D用的shader语言叫ShaderLab,基础语法官方文档地址 //https://docs.unity3d.com/Manual/SL-Shader.html //开头指明名字,可以在别的 ...

  7. Unity3D学习笔记3——Unity Shader的初步使用

    目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...

  8. Vertex and Fragment Shader

    Semantics语义词: 定义:GPU工作时,数据通常暂存在寄存器,那么在Cg中,语义词就指定了输入/输出数据和图形硬件寄存器之间的映射关系. 原理:根据输入语义,图形处理器从某个寄存器取数据:然后 ...

  9. Unity3D 屏幕空间雪场景Shader渲染

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

随机推荐

  1. Visibility属性实现自动隐藏功能

    //使用一个Button,鼠标移入listView显示,移出隐藏 private void button2_MouseEnter(object sender, System.Windows.Input ...

  2. iOS8互动的新通知

    iOS8一旦远程通知想必大家都很熟悉.不要做过多的描述在这里,直接推出iOS8交互式远程通知. 再看互动的通知电话,显示的形式                  如今来看一下详细实现方式 一.通过调用 ...

  3. 【JAVA高级】——myEclipse连接mysql启动数据库服务

    背景: DRP项目要求使用Oracle数据库,但眼下因为种种原因,临时还装不了Oracle.但也不能闲着啊,就拿mysql来试试.安装完mysql以后,使用myEclipse连接数据库,就一直报错,报 ...

  4. 重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试

    原文:重新想象 Windows 8 Store Apps (16) - 控件基础: 依赖属性, 附加属性, 控件的继承关系, 路由事件和命中测试 [源码下载] 重新想象 Windows 8 Store ...

  5. 程序员之---C语言细节22(函数返回指针注意事项&lt;悬空指针&gt;、查看进程能够分配的内存大小)

    主要内容:函数返回指针注意事项<悬空指针>.查看进程能够分配的内存大小 #include <stdio.h> char * favorite_fruit() { static ...

  6. 判断闰年(go语言版本)

    import "strconv" func IsLeapYear(y string) bool { //y == 2000, 2004 //判断是否为闰年 year, _ := s ...

  7. LoaderManager使用具体解释(二)---了解LoaderManager

    了解LoaderManager 这篇文章将介绍LoaderManager类,这是该系列的第二篇文章. 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四:实例: ...

  8. 《反project核心原则》说明

      致亲爱的中国读者: 大家好 !我是<逆向project核心原理> 作者 李承远(ReverseCore). (韩文博客地址:www.reversecore.com) 首先.非常高兴我的 ...

  9. 【BZOJ 1642】 [Usaco2007 Nov]Milking Time 挤奶时间

    1642: [Usaco2007 Nov]Milking Time 挤奶时间 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 590  Solved: 3 ...

  10. java: org.luaj.vm2.LuaError:XXX module not found lua脚本初始化出错(转)

    我遇到这个错误是因为在引用脚本目录时,设置错了位置.设置成脚本所在目录的上级目录. lua使用和加载初始化方法 在java中使用lua,使用需要引用 luaj-jse-2.0.2.jar 同时需要使用 ...