2012-12-26 11:39:47 fg5823820 阅读数 8824

首先着色器来自这里:http://game.ceeger.com/forum/read.php?tid=3162

没有账号的童鞋可以到这里下载这个着色器和脚本:http://pan.baidu.com/share/link?shareid=149713&uk=3087344852

具体使用方法看上面的发的地址。


如果你已经开始使用了这个着色器,就会发现一个严重的问题,那就是在用自己的模型上就会出现各种奇怪的问题,而且蛋疼的是在编辑模式下没问题,运行游戏就有问题!原帖的回帖中也有不少人提到这个问题。

具体我这里的表现是:1、材质变成了蓝色。2、镜面反射完全不正确。

我在大概两周的时间里我都没有找到解决办法,后来还到国外翻到了一个叫MirrorReflection2的着色器,后来发现也是一样,而且这个着色器根本就是有问题的,想知道有什么问题的童鞋就自己去研究吧。


搞技术的就是要解决问题。首先想到的办法是学习着色器自己修改,后来发现这是个坑,看了一些教程后发现都不知道从何开始。后来还是打算慢慢研究为什么在自己的模型上会出错,说实在,我到最后都没搞清楚为什么,可能是顶点法线什么的计算不对吧,不过没关系,最后还是找到了解决办法,倒不如说是偶然发现。


1、材质变成了蓝色。这个是在一个单独的场景里研究发现的,变成蓝色是因为摄像机的背景颜色就是蓝色的!把摄像机背景颜色改成黑色就没问题。

2、反射不正确。具体发现过程略过,其实只是一个很简单的道理。如果说内置Plane能正常反射,那么用内置Plane来反射不就好了。等等,我们之所以使用自己的模型就是因为镜面不是矩形的,用Plane该怎么弄?其实之前想过类型Mask之类的东西不过明显不现实,而其实简单的办法是共享材质。所谓镜面归根到底不过是对材质的修改,那么让Plane接收正确的反射,然后使用了相同材质的模型就得到了正确的反射,不过这个Plane该放哪?我们不希望在场景中看到它。放到镜子后面去不就好了,这里谁都看不到,而且还不会影响镜面效果。

需要注意的是,如果镜面模型很大,而场景进入的时候摄像机看到了模型而看不到Plane,那么模型的材质就是白色的,所以尽量把Plane拉伸到跟模型差不多才能解决这个问题,这大概算是这个方法的弊端,所以如果知道怎么完美的解决方案是最好不过,本文只是抛砖引玉之用。

2014-05-16 16:53:01 baozhenliang 阅读数 6562

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

2018-05-05 23:48:18 ChinarCSDN 阅读数 1130

Unity实现镜面和哈哈镜效果


本文提供全流程,中文翻译。

Chinar 坚持将简单的生活方式,带给世人!

(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)


Chinar —— 心分享、心创新!

助力快速用 Cube Sphere 完成镜面效果

为新手节省宝贵的时间,避免采坑!


Chinar 教程效果:
这里写图片描述



全文高清图片,点击即可放大观看 (很多人竟然不知道)


1

Hint —— 提示


提示:
由于制作过程过于简单

本教程仅用 Unity 提供的标准 Shader ,来实现仅反射天空盒周边环境的镜面效果

如果需要实现真实镜面,反射所有物体,可直接跳转我的另一篇博文

Unity镜子效果的实现 (无需镜子Shader)
举个栗子黑白88


2

Create Resources —— 创建所需资源


我们需要的资源有:

1:Plane —— 对应需创建一个Material,给Plane上色(为了当作地面、参照物。不创建也可)
2:一个Cube —— 对应需创建一个Material,给Cube上色

其他看图即可理解

层次列表结构如下
举个栗子黑白88
这里写图片描述
这里写图片描述


3

Finish —— 完成


基本做完第二步,即可具备镜面效果

但很多人会发现,镜面很模糊

那是因为分辨率默认值很低,需要在 Lighting 中进行设置

分辨率越高、显示效果越清晰、对性能要求越大。请根据自己需求设置默认值!
举个栗子黑白88
这里写图片描述


4

Distorting Mirror —— 哈哈镜


哈哈镜,同理可做一个哈哈镜出来

创建一个 Sphere /球体、将Cube的材质丢到 Sphere 上即可

由于CSDN限制图片5M一下,图片太高清导致只能录制10帧。所以以下动图会很卡
举个栗子黑白88
这里写图片描述


5

Download Demo —— 下载示例


贴心的 Chinar 为大家准备好了 Demo

温馨提示:其实仔细看教程,是不需要下载Demo的
举个栗子黑白88

Chinar Environment Mirror Demo下载


支持

May Be —— 搞开发,总有一天要做的事!


拥有自己的服务器,无需再找攻略!

Chinar 提供一站式教程,闭眼式创建!

为新手节省宝贵时间,避免采坑!


先点击领取 —— 阿里全产品优惠券 (享受最低优惠)


1 —— 云服务器超全购买流程 (新手必备!)

2 —— 阿里ECS云服务器自定义配置 - 购买教程(新手必备!)

3—— Windows 服务器配置、运行、建站一条龙 !

4 —— Linux 服务器配置、运行、建站一条龙 !





技术交流群:806091680 ! Chinar 欢迎你的加入


END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

2018-06-13 17:12:04 weixin_42452001 阅读数 1491

Shader部分代码:

Shader "Custom/FanShe" {
Properties{
_MainTex("Albedo",2D) = "white"{}
_MainTint("Diffuse Color",Color)=(1,1,1,1)
_Cubemap("Cubemap",CUBE) = ""{}
_ReflAmount("Reflection Amount",Range(0.1,1.0))=0.5
}
SubShader{
Tags{"RenderType"="Opaque"}
LOD 200


CGPROGRAM
#pragma surface surf Lambert
#pragma target 3.0
struct Input {
float2 uv_MainTex;
float3 worldRefl;
};
sampler2D _MainTex;
samplerCUBE _Cubemap;
fixed4 _MainTint;
half _ReflAmount;
void surf(Input IN, inout SurfaceOutput o)
{
fixed4 c = tex2D(_MainTex, IN.uv_MainTex)*_MainTint;
o.Albedo = c.rgb;
o.Emission = texCUBE(_Cubemap, IN.worldRefl)*_ReflAmount;
o.Alpha = c.a;
}
ENDCG
}

FallBack "Diffuse"

}


C#部分代码:

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


public class Shader_FanShe : MonoBehaviour {
    public  Cubemap cubeMap;
    public Camera cam;
    Material curmat;
// Use this for initialization
void Start () {
        InvokeRepeating("change", 1, 0.1f);
        curmat = gameObject.GetComponent<Renderer>().material;
        if (curmat == null)
        {
            Debug.Log("cw");
        }
        
}

// Update is called once per frame
void Update () {

}
    void change()
    {
        cam.transform.rotation = Quaternion.identity;
        cam.RenderToCubemap(cubeMap);
        curmat.SetTexture("_Cubemap",cubeMap);
    }

}

镜面反射矩阵推导

阅读数 4639

shader 镜面效果

阅读数 6

没有更多推荐了,返回首页