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. windows phone (26) ApplicationBar应用程序栏

    原文:windows phone (26) ApplicationBar应用程序栏 在应用程序中,如果需要几个按钮或者菜单来执行一些普通的命令,就应该考虑使用ApplicationBar,因为silv ...

  2. Cocos2d-x 脚本语言Lua中的面向对象

    Cocos2d-x 脚本语言Lua中的面向对象 面向对象不是针对某一门语言,而是一种思想.在面向过程的语言也能够使用面向对象的思想来进行编程. 在Lua中,并没有面向对象的概念存在,没有类的定义和子类 ...

  3. Sybase Unwired Platform(SUP) 经常使用资源整理(不断更新中)

    提示:建议刚開始学习的人看三个东西,详见以下的详细内容.然后再去看论坛,官方技术支持站点等资源. SUP移动开发平台 中文视频讲座 SUP入门讲座(Wang Jun) SUP系列学习笔记 SUP实验 ...

  4. PHP+Mysql————表单数据插入数据库及数据提取

    站点在进行新用户注冊时,都会将用户的注冊信息存入数据库中,须要的时候再进行提取.今天写了一个简单的实例. 主要完毕下面几点功能: (1)用户进行注冊,实现password反复确认,验证码校对功能. ( ...

  5. iOS设备定位

    一.iOS谈到定位 1.SignInSignOutViewController.h @interface SignInSignOutViewController : UIViewController& ...

  6. TCP/IP详细说明--滑模、拥塞窗口、慢启动、Negle算法

    TCP的数据流大致能够分为两类,交互数据流与成块的数据流. 交互数据流就是发送控制命令的数据流.比方relogin,telnet.ftp命令等等.成块数据流是用来发送数据的包,网络上大部分的TCP包都 ...

  7. 重新想象 Windows 8 Store Apps (11) - 控件之 ListView 和 GridView

    原文:重新想象 Windows 8 Store Apps (11) - 控件之 ListView 和 GridView [源码下载] 重新想象 Windows 8 Store Apps (11) - ...

  8. android Animation动画的xml使用

    在Android应用程序,使用动画效果,能带给用户更好的感觉,做动画能够通过XML或Android代码来实现. Animation动画效果的实现能够通过两种方式进行实现,一种是tweened anim ...

  9. ios-上拉电阻负载许多其他接口

    想尝试拉加载意识到有多少开始了他的研究之旅,我看了两天做出最终的界面. 之所以这么慢是由于,我不知道要将上拉出现的view放在哪.就能在scrollView拉究竟部的时候被拉出来.还有就是怎么拉出来之 ...

  10. Android开发之Handler和Looper的关系

              关于Handler的总结. Message:消息,当中包括了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理. Handler:处 ...