Created
May 27, 2013 23:01
-
-
Save radiatoryang/5659480 to your computer and use it in GitHub Desktop.
Use with the rest of the EnvCubemap*.cs scripts to implement an environment probe system in your Unity project, with models that'll automatically fetch the closest visible probe. For more info, see: http://www.blog.radiator.debacle.us/2013/05/cubemapped-environment-probes-source.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public class EnvCubemap : MonoBehaviour { | |
public Cubemap cubemap; | |
public int cubemapRes = 128; // powers of two only | |
public CameraClearFlags clearFlags = CameraClearFlags.Color; | |
public Color clearColor = Color.black; | |
public LayerMask cullingMask; | |
public float near = 0.1f; | |
public float far = 10000f; | |
public void KillThis( GameObject go ) { | |
DestroyImmediate( go ); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEditor; | |
class CubemapUtility { | |
[MenuItem( "Cubemaps/Bake all static cubemaps" )] | |
static void BakeCubemaps() { | |
// default path to save cubemaps if the scene hasn't been saved yet | |
string assetPath = "Assets/radiator/cubemaps/"; | |
// ... otherwise, save the cubemaps in a folder next to the scene; | |
// NOTE: this will NOT delete the existing cubemaps, so you might end up having to clean the folder yourself | |
if (EditorApplication.currentScene != "") { | |
List<string> pathTemp = new List<string>(EditorApplication.currentScene.Split(char.Parse("/"))); | |
pathTemp[pathTemp.Count-1] = pathTemp[pathTemp.Count-1].Substring(0, pathTemp[pathTemp.Count-1].Length - 6); | |
assetPath = string.Join( "/", pathTemp.ToArray() ) + "/"; | |
} | |
// begin baking cubemaps | |
float progress = 0f; // how far along we are in the whole baking process, from 0-1 | |
int counter = 0; // number of cubemaps we've processed so far | |
EnvCubemap[] cubemaps = GameObject.FindObjectsOfType( typeof( EnvCubemap ) ) as EnvCubemap[]; // grab all cubemaps in the scene | |
foreach ( EnvCubemap env_cubemap in cubemaps ) { | |
EditorUtility.DisplayProgressBar("Baking cubemaps...", "Baking cubemap at " + env_cubemap.transform.position.ToString(), progress); | |
if (env_cubemap.enabled) { | |
Cubemap cube = BakeCubemapStatic(env_cubemap); | |
env_cubemap.cubemap = cube; // I probably should've named these variables better | |
string cubeAsset = assetPath + cube.name + ".cubemap"; // cubemap files must end with .cubemap file extension | |
AssetDatabase.CreateAsset( cube, cubeAsset); | |
EditorUtility.SetDirty( cube ); // use SetDirty() to tell Unity to save new info | |
EditorUtility.SetDirty( env_cubemap ); | |
} | |
counter++; // we finished processing a cubemap! yay! | |
progress = (counter * 1f) / cubemaps.Length; // multiply by 1f to cast int to a float | |
} | |
EditorUtility.ClearProgressBar(); | |
} | |
static Cubemap BakeCubemapStatic(EnvCubemap env_cubemap) { | |
// create new cubemap | |
Cubemap cubemap = new Cubemap( env_cubemap.cubemapRes, TextureFormat.RGB24, true ); | |
// create temporary camera for rendering | |
var go = new GameObject( "CubemapCamera", typeof( Camera ) ); | |
// place it on the object | |
go.transform.position = env_cubemap.transform.position; | |
go.transform.rotation = Quaternion.identity; | |
// render into cubemap | |
go.camera.near = env_cubemap.near; | |
go.camera.far = env_cubemap.far; | |
go.camera.clearFlags = env_cubemap.clearFlags; | |
go.camera.backgroundColor = env_cubemap.clearColor; | |
go.camera.cullingMask = env_cubemap.cullingMask; | |
go.camera.RenderToCubemap( cubemap, 63 ); | |
// destroy temporary camera | |
env_cubemap.KillThis( go ); | |
// some cubemappy stuff | |
cubemap.SmoothEdges(); | |
cubemap.mipMapBias = 0.5f; | |
cubemap.name = env_cubemap.cubemapRes.ToString() + "@" + env_cubemap.transform.position.ToString(); | |
cubemap.Apply( true, false ); | |
return cubemap; | |
} | |
// if the cubemap baker crashes, you'll have to use this to clear the progress bar | |
[MenuItem( "Cubemaps/Debug, clear progress bar" )] | |
static void Clear() { | |
EditorUtility.ClearProgressBar(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
using System.Collections.Generic; | |
public class EnvCubemapCatcher : MonoBehaviour { | |
public EnvCubemap cubemap; | |
public Renderer myRenderer; // optional, assign in inspector | |
public static List<EnvCubemap> allCubemaps = new List<EnvCubemap>(); | |
public bool useOnlyLosCubemaps = false; // if true: use only cubemaps with LoS... more expensive, must raycast | |
public LayerMask losMask; // the raycast mask used to determine if cubemap has LoS to this script | |
void Awake() { | |
allCubemaps.Clear(); | |
} | |
// Use this for initialization | |
void Start () { | |
if ( !myRenderer ) | |
myRenderer = renderer; | |
if ( allCubemaps.Count == 0 ) { | |
RefreshCubemapList(); | |
} | |
StartCoroutine( UpdateCubemaps() ); | |
} | |
public static void RefreshCubemapList() { // could be called in-game, perhaps, too? | |
allCubemaps.AddRange( GameObject.FindObjectsOfType( typeof( EnvCubemap ) ) as EnvCubemap[] ); | |
Debug.Log( "EnvCubemapCatcher.Refresh(), grabbed " + allCubemaps.Count + " env_cubemaps!" ); | |
} | |
IEnumerator UpdateCubemaps() { | |
const float timestep = 0.5f; // cubemap detection doesn't have to happen that frequently | |
while ( true ) { | |
// cache old env_cubemap | |
EnvCubemap oldCubemap = cubemap; | |
// find the closest env_cubemap | |
float closestSqrMagnitude = 100000f; | |
foreach ( EnvCubemap cube in allCubemaps ) { | |
// use a sqrMagnitude check as the cheapest possible early-out | |
float sqrMagnitude = (cube.transform.position - transform.position).sqrMagnitude; | |
if ( sqrMagnitude < closestSqrMagnitude && (!useOnlyLosCubemaps || !Physics.Raycast(transform.position, cube.transform.position - transform.position, Mathf.Sqrt(sqrMagnitude), losMask ) ) ) { | |
closestSqrMagnitude = sqrMagnitude; | |
cubemap = cube; | |
} | |
} | |
if ( myRenderer ) { | |
if ( oldCubemap != cubemap ) { // if the new cubemap doesn't match the old one, change it | |
Debug.DrawLine( transform.position, cubemap.transform.position, Color.magenta, 1f ); | |
myRenderer.material.SetTexture( "_Cube", cubemap.cubemap ); | |
} | |
} else { | |
Debug.LogWarning( "EnvCubemapCatcher can't find its renderer! " + transform.position.ToString() ); | |
} | |
yield return new WaitForSeconds(timestep); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment