Log in or register to post comments

Mirror reflections

August 26, 2014 - 1:47pm #1

I am currently trying to make a car reflection on a highly reflective surface plane using the water pro package of Unity. I have also tried to use various mirror reflections scripts/shaders available on unity forums. 
These setups give me perfect reflection results in my scene and game windows when played back. My problem is the end result on my Android mobile is that the car reflection itself is rendered repeatedly without erasing its prior motion/rotation… kind of like a golf swing in full motion to study the actual movement. I also seem to get a very noisy and colored background reflection where the car is not rendered on the plane where the reflection appears. What am I doing wrong? If I remove the car/gameobjects/assets from being parented to the Vuforia Image Target... I still get the continuous reflections being rendered like the full movement of a golf swing 

Please advise. 

Cheers,

Olivier.

 

Here is my shader script:

Shader "FX/Mirror Reflection" { 
Properties {
    _MainTex ("Base (RGB)"2D) = "white" {}
    _ReflectionTex ("Reflection"2D) = "white" { TexGen ObjectLinear }
}

// two texture cardsfull thing
Subshader { 
    Pass {
        SetTexture[_MainTex] { combine texture }
        SetTexture[_ReflectionTex] { matrix [_ProjMatrixcombine texture * previous }
    }
}

// fallbackjust main texture
Subshader {
    Pass {
        SetTexture [_MainTex] { combine texture }
    }
}

}

 

AND HERE IS MY MIRROR REFLECTION SCRIPT:

 

using UnityEngine;

using System.Collections;

// This is in fact just the Water script from Pro Standard Assets,
// just with refraction stuff removed.

[ExecuteInEditMode// Make mirror live-update even when not in play mode
public class MirrorReflection : MonoBehaviour
{
    public bool m_DisablePixelLights = true;
    public int m_TextureSize = 256;
    public float m_ClipPlaneOffset = 0.07f;
    
    public LayerMask m_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
    // cameraWe render reflections and do other updates here.
    // Because the script executes in edit modereflections 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.        
        ifs_InsideRendering )
            return;
        s_InsideRendering = true;
        
        Camera reflectionCamera;
        CreateMirrorObjectscamout reflectionCamera );
        
        // find out the reflection planeposition and normal in world space
        Vector3 pos = transform.position;
        Vector3 normal = transform.up;
        
        // Optionally disable pixel lights for reflection
        int oldPixelLightCount = QualitySettings.pixelLightCount;
        ifm_DisablePixelLights )
            QualitySettings.pixelLightCount = 0;
        
        UpdateCameraModescamreflectionCamera );
        
        // Render reflection
        // Reflect camera around reflection plane
        float d = -Vector3.Dot (normalpos) - m_ClipPlaneOffset;
        Vector4 reflectionPlane = new Vector4 (normal.xnormal.ynormal.zd);
    
        Matrix4x4 reflection = Matrix4x4.zero;
        CalculateReflectionMatrix (ref reflectionreflectionPlane);
        Vector3 oldpos = cam.transform.position;
        Vector3 newpos = reflection.MultiplyPointoldpos );
        reflectionCamera.worldToCameraMatrix = cam.worldToCameraMatrix * reflection;
    
        // Setup oblique projection matrix so that near plane is our reflection
        // planeThis way we clip everything below/above it for free.
        Vector4 clipPlane = CameraSpacePlanereflectionCameraposnormal1.0f );
        Matrix4x4 projection = cam.projectionMatrix;
        CalculateObliqueMatrix (ref projectionclipPlane);
        reflectionCamera.projectionMatrix = projection;
        
        reflectionCamera.cullingMask = ~(1<<4) & m_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(0euler.yeuler.z);
        reflectionCamera.Render();
        reflectionCamera.transform.position = oldpos;
        GL.SetRevertBackfacing (false);
        Material[] materials = renderer.sharedMaterials;
        foreachMaterial mat in materials ) {
            ifmat.HasProperty("_ReflectionTex") )
                mat.SetTexture"_ReflectionTex"m_ReflectionTexture );
        }
        
        // Set matrix on the shader that transforms UVs from object space into screen
        // spaceWe want to just project reflection texture on screen.
        Matrix4x4 scaleOffset = Matrix4x4.TRS(
            new Vector3(0.5f,0.5f,0.5f), Quaternion.identitynew Vector3(0.5f,0.5f,0.5f) );
        Vector3 scale = transform.lossyScale;
        Matrix4x4 mtx = transform.localToWorldMatrix * Matrix4x4.Scalenew Vector3(1.0f/scale.x1.0f/scale.y1.0f/scale.z) );
        mtx = scaleOffset * cam.projectionMatrix * cam.worldToCameraMatrix * mtx;
        foreachMaterial mat in materials ) {
            mat.SetMatrix"_ProjMatrix"mtx );
        }
        
        // Restore pixel light count
        ifm_DisablePixelLights )
            QualitySettings.pixelLightCount = oldPixelLightCount;
        
        s_InsideRendering = false;
    }
    
    
    // Cleanup all the objects we possibly have created
    void OnDisable()
    {
        ifm_ReflectionTexture ) {
            DestroyImmediatem_ReflectionTexture );
            m_ReflectionTexture = null;
        }
        foreachDictionaryEntry kvp in m_ReflectionCameras )
            DestroyImmediate( ((Camera)kvp.Value).gameObject );
        m_ReflectionCameras.Clear();
    }
    
    
    private void UpdateCameraModesCamera srcCamera dest )
    {
        ifdest == null )
            return;
        // set camera to clear the same way as current camera
        dest.clearFlags = src.clearFlags;
        dest.backgroundColor = src.backgroundColor;        
        ifsrc.clearFlags == CameraClearFlags.Skybox )
        {
            Skybox sky = src.GetComponent(typeof(Skybox)) as Skybox;
            Skybox mysky = dest.GetComponent(typeof(Skybox)) as Skybox;
            if( !sky || !sky.material )
            {
                mysky.enabled = false;
            }
            else
            {
                mysky.enabled = true;
                mysky.material = sky.material;
            }
        }
        // update other values to match current camera.
        // even if we are supplying custom camera&projection matrices,
        // some of values are used elsewhere (e.gskybox uses far plane)
        dest.farClipPlane = src.farClipPlane;
        dest.nearClipPlane = src.nearClipPlane;
        dest.orthographic = src.orthographic;
        dest.fieldOfView = src.fieldOfView;
        dest.aspect = src.aspect;
        dest.orthographicSize = src.orthographicSize;
    }
    
    // On-demand create any objects we need
    private void CreateMirrorObjectsCamera currentCameraout Camera reflectionCamera )
    {
        reflectionCamera = null;
        
        // Reflection render texture
        if( !m_ReflectionTexture || m_OldReflectionTextureSize != m_TextureSize )
        {
            ifm_ReflectionTexture )
                DestroyImmediatem_ReflectionTexture );
            m_ReflectionTexture = new RenderTexturem_TextureSizem_TextureSize16 );
            m_ReflectionTexture.name = "__MirrorReflection" + GetInstanceID();
            m_ReflectionTexture.isPowerOfTwo = true;
            m_ReflectionTexture.hideFlags = HideFlags.DontSave;
            m_OldReflectionTextureSize = m_TextureSize;
        }
        
        // Camera for reflection
        reflectionCamera = m_ReflectionCameras[currentCameraas 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;
        }        
    }
    
    // Extended signreturns -10 or 1 based on sign of a
    private static float sgn(float a)
    {
        if (a > 0.0freturn 1.0f;
        if (a < 0.0freturn -1.0f;
        return 0.0f;
    }
    
    // Given position/normal of the planecalculates plane in camera space.
    private Vector4 CameraSpacePlane (Camera camVector3 posVector3 normalfloat sideSign)
    {
        Vector3 offsetPos = pos + normal * m_ClipPlaneOffset;
        Matrix4x4 m = cam.worldToCameraMatrix;
        Vector3 cpos = m.MultiplyPointoffsetPos );
        Vector3 cnormal = m.MultiplyVectornormal ).normalized * sideSign;
        return new Vector4cnormal.xcnormal.ycnormal.z, -Vector3.Dot(cpos,cnormal) );
    }
    
    // Adjusts the given projection matrix so that near plane is the given clipPlane
    // clipPlane is given in camera spaceSee article in Game Programming Gems 5.
    private static void CalculateObliqueMatrix (ref Matrix4x4 projectionVector4 clipPlane)
    {
        Vector4 q = projection.inverse * new Vector4(
            sgn(clipPlane.x),
            sgn(clipPlane.y),
            1.0f,
            1.0f
        );
        Vector4 c = clipPlane * (2.0F / (Vector4.Dot (clipPlaneq)));
        // third row = clip plane - fourth row
        projection[2] = c.x - projection[3];
        projection[6] = c.y - projection[7];
        projection[10] = c.z - projection[11];
        projection[14] = c.w - projection[15];
    }

    // Calculates reflection matrix around the given plane
    private static void CalculateReflectionMatrix (ref Matrix4x4 reflectionMatVector4 plane)
    {
        reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);
        reflectionMat.m01 = (   - 2F*plane[0]*plane[1]);
        reflectionMat.m02 = (   - 2F*plane[0]*plane[2]);
        reflectionMat.m03 = (   - 2F*plane[3]*plane[0]);

        reflectionMat.m10 = (   - 2F*plane[1]*plane[0]);
        reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);
        reflectionMat.m12 = (   - 2F*plane[1]*plane[2]);
        reflectionMat.m13 = (   - 2F*plane[3]*plane[1]);
    
        reflectionMat.m20 = (   - 2F*plane[2]*plane[0]);
        reflectionMat.m21 = (   - 2F*plane[2]*plane[1]);
        reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);
        reflectionMat.m23 = (   - 2F*plane[3]*plane[2]);

        reflectionMat.m30 = 0F;
        reflectionMat.m31 = 0F;
        reflectionMat.m32 = 0F;
        reflectionMat.m33 = 1F;
    }
}

AttachmentSize
Image icon Screenshot_2014-08-26-13-13-29.jpg330.71 KB
Log in or register to post comments