/// <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); } }
/// <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); } }
// ######################## 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); }
/// <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)); }
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); }
public static void CreateVolumetricCapsule(MenuCommand menuCommand) { VolumetricObject vo = CreateVolumetricObject(menuCommand, Types.CAPSULE, "VolumetricCapsule"); }
// ######################## 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; } }