Example #1
0
 /// <summary>
 /// Removes the Object from the Renderer
 /// </summary>
 /// <param name="obj"></param>
 public static void Remove(VolumetricObject obj)
 {
     if (_objs != null && _objs.Contains(obj))
     {
         _objs.Remove(obj);
     }
 }
Example #2
0
    /// <summary>
    /// Adds the Volumetric Objects to teh Renderer if it is not registered yet
    /// </summary>
    /// <param name="obj"></param>
    public static void AddObj(VolumetricObject obj)
    {
        if (_objs == null)
        {
            _objs = new List <VolumetricObject>();
        }

        if (!_objs.Contains(obj))
        {
            _objs.Add(obj);
        }
    }
Example #3
0
    // ######################## FUNCTIONALITY ######################## //

    #region EDITOR
    #if UNITY_EDITOR
    /// <summary>
    /// Creates a Volumetric Object
    /// </summary>
    /// <param name="menuCommand"></param>
    /// <param name="type"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    private static VolumetricObject CreateVolumetricObject(MenuCommand menuCommand, Types type, string name)
    {
        VolumetricObjectsRenderer rend = Camera.main.GetComponent <VolumetricObjectsRenderer>();

        if (rend == null)
        {
            Camera.main.gameObject.AddComponent <VolumetricObjectsRenderer>();
        }

        // create the Object
        GameObject       obj = new GameObject(name, typeof(VolumetricObject));
        VolumetricObject vo  = obj.GetComponent <VolumetricObject>();

        // set type
        vo.Type = type;

        // Ensure it gets reparented if this was a context click (otherwise does nothing)
        GameObjectUtility.SetParentAndAlign(obj, menuCommand.context as GameObject);
        // Register the creation in the undo system
        Undo.RegisterCreatedObjectUndo(obj, "Create " + obj.name);
        Selection.activeObject = obj;
        return(vo);
    }
Example #4
0
 /// <summary>
 /// Returns true if the Volumetric Object is reguistered in the Renderer
 /// </summary>
 /// <param name="obj"></param>
 /// <returns></returns>
 public static bool Contains(VolumetricObject obj)
 {
     return(_objs != null && _objs.Contains(obj));
 }
Example #5
0
    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        // if for some reason there is no material or if there are no Objects, do nothing
        if (!EffectMaterial || _objs == null || _objs.Count == 0)
        {
            Graphics.Blit(src, dest);
            return;
        }

        // sort the Objects by depth
        _objs.Sort((x, y) => (int)Mathf.Clamp(CurrentCamera.transform.InverseTransformPoint(y.transform.position).z - CurrentCamera.transform.InverseTransformPoint(x.transform.position).z, -1, 1));

        // set general shader values for camera
        EffectMaterial.SetMatrix("_FrustumCornersES", GetFrustumCorners(CurrentCamera));
        EffectMaterial.SetMatrix("_CameraInvViewMatrix", CurrentCamera.cameraToWorldMatrix);
        EffectMaterial.SetVector("_CameraWS", CurrentCamera.transform.position);

        // set general shader values for raymarching
        EffectMaterial.SetVector("_RaymarchingParams", new Vector4(StepCount, StepCountInsideVolume, StepSize, DrawDist));

        // create to temporary Render textures as buffers
        RenderTexture temp0 = RenderTexture.GetTemporary(src.width, src.height, 0, src.format);
        RenderTexture temp1 = RenderTexture.GetTemporary(src.width, src.height, 0, src.format);

        // this is a variable for storing which buffer we last used
        int lastUsed = 0;

        // render all objects
        for (int i = 0; i < _objs.Count; ++i)
        {
            VolumetricObject obj = _objs[i];
            // set shader values that are type dependend
            VolumetricObject.Types t = obj.Type;
            switch (t)
            {
            case VolumetricObject.Types.BOX:
                EffectMaterial.SetInt("_Type", 0);
                EffectMaterial.SetVector("_BoxDimensions", obj.Dimensions * 0.5f);
                break;

            case VolumetricObject.Types.SPHERE:
                EffectMaterial.SetInt("_Type", 1);
                EffectMaterial.SetFloat("_SphereRad", obj.Radius);
                break;

            case VolumetricObject.Types.CAPSULE:
                EffectMaterial.SetInt("_Type", 2);
                EffectMaterial.SetMatrix("_CapsuleBounds", obj.CapsuleParams);
                break;
            }

            // set non type dependent per Object values
            EffectMaterial.SetColor("_Color", obj.Color);

            Color dc = obj.DenseColor;
            dc.a = obj.UseDenseColor ? 1 : 0;
            EffectMaterial.SetColor("_DenseColor", dc);

            EffectMaterial.SetVector("_FogOptions", new Vector4(obj.Density, (float)obj.Falloff, (float)obj.BlendMode, 0));
            EffectMaterial.SetMatrix("_Noise_STO", obj.NoiseSTO);
            EffectMaterial.SetMatrix("_InvModel", obj.transform.localToWorldMatrix.inverse);

            // render the Object by alternating between buffers
            if (i == 0)
            {
                CustomGraphicsBlit(src, temp0, EffectMaterial, 0);
                lastUsed = 0;
            }
            else if (i % 2 == 0)
            {
                CustomGraphicsBlit(temp1, temp0, EffectMaterial, 0);
                lastUsed = 0;
            }
            else
            {
                CustomGraphicsBlit(temp0, temp1, EffectMaterial, 0);
                lastUsed = 1;
            }
        }

        // render final render texture
        Graphics.Blit(lastUsed == 1 ? temp1 : temp0, dest);

        // clean up buffers
        RenderTexture.ReleaseTemporary(temp0);
        RenderTexture.ReleaseTemporary(temp1);
    }
Example #6
0
 public static void CreateVolumetricCapsule(MenuCommand menuCommand)
 {
     VolumetricObject vo = CreateVolumetricObject(menuCommand, Types.CAPSULE, "VolumetricCapsule");
 }
Example #7
0
    // ######################## UNITY EVENT FUNCTIONS ######################## //
    public override void OnInspectorGUI()
    {
        VolumetricObject vo = (VolumetricObject)target;

        VolumetricObject.Types t = vo.Type;

        EditorGUI.BeginChangeCheck();
        float density = EditorGUILayout.FloatField(new GUIContent("Density", "Determines how far you can look through the fog"), vo.Density);

        VolumetricObject.FalloffTypes falloff = (VolumetricObject.FalloffTypes)EditorGUILayout.EnumPopup(new GUIContent("Falloff", "Defines the Falloff curve of the Fog. SQUARED_EXPONENTIAL is the most realistic"), vo.Falloff);



        EditorGUILayout.Space();
        EditorGUILayout.LabelField("Color", EditorStyles.boldLabel);
        Color color         = EditorGUILayout.ColorField("Color", vo.Color);
        bool  useDenseColor = EditorGUILayout.Toggle(new GUIContent("Use Dense Color", "If enabled, the color will be blended with a second color that gets stronger the denser the fog is"), vo.UseDenseColor);
        Color denseColor    = vo.DenseColor;

        if (useDenseColor)
        {
            EditorGUI.indentLevel++;
            denseColor = EditorGUILayout.ColorField("Dense Color", vo.DenseColor);
            EditorGUI.indentLevel--;
        }



        EditorGUILayout.Space();
        VolumetricObject.BlendModes blendmode = (VolumetricObject.BlendModes)EditorGUILayout.EnumPopup("Blend Mode", vo.BlendMode);



        EditorGUILayout.Space();
        EditorGUILayout.LabelField("Noise", EditorStyles.boldLabel);
        bool enableNoise = EditorGUILayout.Toggle(new GUIContent("Enable Noise", "If true, a simplex noise is added to the volume"), vo.EnableNoise);

        Matrix4x4 noiseSto = vo.NoiseSTO;

        if (enableNoise)
        {
            EditorGUI.indentLevel++;
            bool    globalNoise    = EditorGUILayout.Toggle(new GUIContent("Global", "If true, the noise is calculated in world space"), vo.GlobalNoise);
            Vector3 noiseScale     = EditorGUILayout.Vector3Field("Scale", new Vector3(vo.NoiseSTO[0, 0], vo.NoiseSTO[0, 1], vo.NoiseSTO[0, 2]));
            Vector3 noiseTransform = EditorGUILayout.Vector3Field("Offset", new Vector3(vo.NoiseSTO[1, 0], vo.NoiseSTO[1, 1], vo.NoiseSTO[1, 2]));
            float   noiseStrenght  = EditorGUILayout.Slider("Strength", vo.NoiseSTO[2, 1], 0, 1);
            EditorGUI.indentLevel--;

            noiseSto[0, 0] = noiseScale.x;
            noiseSto[0, 1] = noiseScale.y;
            noiseSto[0, 2] = noiseScale.z;
            noiseSto[1, 0] = noiseTransform.x;
            noiseSto[1, 1] = noiseTransform.y;
            noiseSto[1, 2] = noiseTransform.z;
            noiseSto[2, 0] = 1;
            noiseSto[2, 1] = noiseStrenght;
            noiseSto[2, 2] = globalNoise ? 1 : 0;
        }
        else
        {
            noiseSto[2, 0] = 0;
        }



        EditorGUILayout.Space();
        EditorGUILayout.LabelField("Object", EditorStyles.boldLabel);

        VolumetricObject.Types type = (VolumetricObject.Types)EditorGUILayout.EnumPopup("Type", t);



        EditorGUILayout.Space();
        Vector3   dimensions = vo.Dimensions;
        float     radius     = vo.Radius;
        Matrix4x4 bounds     = vo.CapsuleParams;

        switch (t)
        {
        case VolumetricObject.Types.BOX:
            dimensions = EditorGUILayout.Vector3Field(new GUIContent("Dimensions", "The X, Y and Z Dimensions of the Box"), vo.Dimensions);
            break;

        case VolumetricObject.Types.SPHERE:
            radius = EditorGUILayout.FloatField("Radius", vo.Radius);
            break;

        case VolumetricObject.Types.CAPSULE:
            Vector3 bounds1 = EditorGUILayout.Vector3Field(new GUIContent("Point 1", "The center of the first Capsule Sphere"), new Vector3(vo.CapsuleParams[0, 0], vo.CapsuleParams[0, 1], vo.CapsuleParams[0, 2]));
            Vector3 bounds2 = EditorGUILayout.Vector3Field(new GUIContent("Point 2", "The center of the second Capsule Sphere"), new Vector3(vo.CapsuleParams[1, 0], vo.CapsuleParams[1, 1], vo.CapsuleParams[1, 2]));

            bounds[0, 0] = bounds1.x;
            bounds[0, 1] = bounds1.y;
            bounds[0, 2] = bounds1.z;
            bounds[1, 0] = bounds2.x;
            bounds[1, 1] = bounds2.y;
            bounds[1, 2] = bounds2.z;
            bounds[2, 0] = EditorGUILayout.FloatField("Radius", vo.CapsuleParams[2, 0]);
            break;
        }

        if (EditorGUI.EndChangeCheck())
        {
            Undo.RecordObject(vo, $"Changed {vo.name}");

            vo.Color         = color;
            vo.DenseColor    = denseColor;
            vo.UseDenseColor = useDenseColor;
            vo.BlendMode     = blendmode;
            vo.Density       = density;
            vo.Falloff       = falloff;
            vo.NoiseSTO      = noiseSto;
            vo.Type          = type;
            vo.Dimensions    = dimensions;
            vo.Radius        = radius;
            vo.CapsuleParams = bounds;
        }
    }