Unity3d 镜面反射 vertex and frag Shader源代码

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

时间: 2024-11-10 15:53:46

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

Unity3d 镜面反射 vertex and frag Shader源码

Unity3d 镜面反射 网上能找到的基本上是固定管道或表面渲染的shader, 特此翻译为顶点.片段渲染的Shader, 本源码只涉及shader与cs部分, Editor部分使用NGUI绘制的, 请自行下载NGUI unity3d 版本:v4.3.1 ReflectionEffect.cs using UnityEngine; using System.Collections; using System; /// <summary> /// 反射效果 /// </summary>

Unity3d 镜面折射 vertex and frag Shader源码

Unity3d 镜面折射 网上能找到的基本上是固定管道或表面渲染的shader, 特此翻译为顶点.片段渲染的Shader, 本源码只涉及shader与cs部分, 请自行下载NGUI unity3d 版本:v4.3.1 RefractionMirror.cs using UnityEngine; using System.Collections; using System; /// <summary> /// 镜面折射效果 /// </summary> [AddComponentMe

Unity3D之高级渲染-Shader Forge

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 在前面的博客中给读者介绍了关于使用Shader Forge的应用,Shader Forge这个组件使用起来还是非常方便的,尤其对于哪些对Shader编程不是很理解的开发者,使用它可以

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

顶点片段着色器 V&F Shader:英文全称Vertex and Fragment Shader,最强大的Shader类型,也是我们在使用ShaderLab中的重点部分,属于可编程管线,使用的是CG/HLSL语法.分为vertex顶点部分和Fragment像素部分. 本篇的末尾讲述顶点函数传入的结构体类型的参数appdata_base. Shader "Custom/Exam1" { Properties { _MainTex ("Texture", 2D

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

笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解>电子工业出版社等. CSDN视频网址:http://edu.csdn.net/lecturer/144 大家了解了Shader Forge的制作原理,也会使用Shader Forge制作渲染材质了,在实际项目开发中,我们会遇到各种各样的问题,有时候我们需要使用Shader Forge渲

Unity3D 2D Sprite描边效果Shader,可手动调整效果适配

最近两个月学了很多Shader的知识,现在也算入点门了.现在网上有很多2D描边的Shader,说实话大多数很差劲.有些多余的条件判断影响效率,提供的参数也不够适配所有图片.因为美术喜欢在图片上面加一些效果,再加上切图的时候背景图的透明部分不够多,或者透明通道透明不彻底等等问题,2D图片描边效果通常都不尽如人意.这种情况一般是要从美术那边用ps做调整,如果需要描边切图周围需要留出一点区域,我这个Shader提供了两个参数可以调整效果,检测范围和描边粗细,根据图片的不同,参数肯定要做些调整才能达到最

3D Computer Grapihcs Using OpenGL - 07 Passing Data from Vertex to Fragment Shader

上节的最后我们实现了两个绿色的三角形,而绿色是直接在Fragment Shader中指定的. 这节我们将为这两个三角形进行更加自由的着色--五个顶点各自使用不同的颜色. 要实现这个目的,我们分两步进行,首先 在顶点数组里增加数据用来表示颜色 修改sendDataToOpenGL()函数中的verts数组: 1 GLfloat verts[] = 2 { 3 +0.0f, +0.0f, //Vertex 0 4 +1.0, +0.0, +0.0f, //Color 0 5 +1.0f, +1.0f

在Unity3D中开发的Rim Shader

Swordmaster Rim Shaders 特点 本资源包共包含两种Rim效果的Shader (1)Rim Bumped Specular. (2)Rim StandardPBR(Metallic setup). (3)Rim StandardPBR(Specular setup). 它们都是顶点片元Shader,由本人手动编写完成: The Rim Bumped Specular shader: 创建一个材质球并设置Shader为Rim Bumped Specular: 你可以通过这些属性

在Unity3D中开发的Ghost Shader

SwordMaster Ghost Shader 特点 此Shader是顶点片元Shader,由本人手动编写完成 此Shader已经在移动设备真机上进行过测试,可以直接应用到您的项目中 所支持的Unity的版本 5.6.6 或 更高 下载地址 您可以从Unity Asset Store上进行下载:SwordMaster Ghost Shader 更多插件请访问本人的个人网站: https://www.swordmaster.info/ 原文地址:https://www.cnblogs.com/S