Skip to content

Instantly share code, notes, and snippets.

@bcatcho
Created October 27, 2013 17:32
Show Gist options
  • Save bcatcho/7185422 to your computer and use it in GitHub Desktop.
Save bcatcho/7185422 to your computer and use it in GitHub Desktop.
lightprobe lighting in unity3d: This was a quick test made in a couple of hours. Seems to get the job done.
using UnityEngine;
using System.Collections;
public class lightprobemanager : MonoBehaviour
{
public Color ambient;
public Light[] lights;
private float[] _coefficients;
private int _probeCount;
private const int _coefficientsPerProbe = 27;
private Vector3[] _probePositions;
void Start()
{
LightmapSettings.lightProbes = Instantiate(LightmapSettings.lightProbes) as LightProbes;
_coefficients = LightmapSettings.lightProbes.coefficients;
_probeCount = LightmapSettings.lightProbes.count;
_probePositions = LightmapSettings.lightProbes.positions;
}
void UpdateLightProbes()
{
int i = 0;
i = 0;
while (i < _coefficients.Length)
{
_coefficients[i] = 0f;
i++;
}
// i =0;
// while (i < _probeCount)
// {
// AddSHAmbientLight(ambient, _coefficients, i * _coefficientsPerProbe);
// i++;
// }
foreach (Light l in lights)
{
if (l.type == LightType.Directional)
{
i = 0;
while (i < _probeCount)
{
AddSHDirectionalLight(l.color, -l.transform.forward, l.intensity, _coefficients, i * _coefficientsPerProbe);
i++;
}
}
else if (l.type == LightType.Point)
{
i = 0;
while (i < _probeCount)
{
AddSHPointLight(l.color, l.transform.position, l.range, l.intensity, _coefficients, i * _coefficientsPerProbe, _probePositions[i]);
i++;
}
}
}
LightmapSettings.lightProbes.coefficients = _coefficients;
}
void Update()
{
UpdateLightProbes();
}
void AddSHAmbientLight(Color color, float[] coefficients, int index)
{
float k2SqrtPI = 3.54490770181F;
coefficients[index + 0] += color.r * k2SqrtPI;
coefficients[index + 1] += color.g * k2SqrtPI;
coefficients[index + 2] += color.b * k2SqrtPI;
}
void AddSHDirectionalLight(Color color, Vector3 direction, float intensity, float[] coefficients, int index)
{
float kInv2SqrtPI = 0.28209479177F;
float kSqrt3Div2SqrtPI = 0.4886025119F;
float kSqrt15Div2SqrtPI = 1.09254843059F;
float k3Sqrt5Div4SqrtPI = 0.94617469576F;
float kSqrt15Div4SqrtPI = 0.5462742153F;
float kOneThird = 0.33333333333F;
float[] dirFactors = new float[9];
dirFactors[0] = kInv2SqrtPI;
dirFactors[1] = -direction.y * kSqrt3Div2SqrtPI;
dirFactors[2] = direction.z * kSqrt3Div2SqrtPI;
dirFactors[3] = -direction.x * kSqrt3Div2SqrtPI;
dirFactors[4] = direction.x * direction.y * kSqrt15Div2SqrtPI;
dirFactors[5] = -direction.y * direction.z * kSqrt15Div2SqrtPI;
dirFactors[6] = (direction.z * direction.z - kOneThird) * k3Sqrt5Div4SqrtPI;
dirFactors[7] = -direction.x * direction.z * kSqrt15Div2SqrtPI;
dirFactors[8] = (direction.x * direction.x - direction.y * direction.y) * kSqrt15Div4SqrtPI;
float kNormalization = 2.95679308573F;
intensity *= 2.0F;
float rscale = color.r * intensity * kNormalization;
float gscale = color.g * intensity * kNormalization;
float bscale = color.b * intensity * kNormalization;
int i = 0;
while (i < 9)
{
float c = dirFactors[i];
coefficients[index + 3 * i + 0] += c * rscale;
coefficients[index + 3 * i + 1] += c * gscale;
coefficients[index + 3 * i + 2] += c * bscale;
++i;
}
}
void AddSHPointLight(Color color, Vector3 position, float range, float intensity, float[] coefficients, int index, Vector3 probePosition)
{
Vector3 probeToLight = position - probePosition;
float attenuation = 1.0F / (1.0F + 25.0F * probeToLight.sqrMagnitude / range * range);
AddSHDirectionalLight(color, probeToLight.normalized, intensity * attenuation, coefficients, index);
}
#if UNITY_EDITOR
public bool GenerateProbeGrid = false;
public float ProbeGridCellSize = .5f;
public Bounds ProbeGridSize;
private void OnDrawGizmosSelected()
{
Gizmos.DrawWireCube(transform.position + ProbeGridSize.center, ProbeGridSize.size);
}
private void RegenerateProbeGrid()
{
int width = Mathf.RoundToInt( ProbeGridSize.size.x / ProbeGridCellSize);
int depth = Mathf.RoundToInt( ProbeGridSize.size.z / ProbeGridCellSize);
var probeLocations = new Vector3[width * depth + 1];
// now do the grid
for(int w = 0; w < width; w++)
{
for(int d = 0; d < depth; d++)
{
probeLocations[w*width + d] = ProbeGridSize.min + new Vector3(w, 0, d) * ProbeGridCellSize;
}
}
// first add a probe high up to make it a volume
probeLocations[width * depth] = ProbeGridSize.center+Vector3.up*ProbeGridSize.extents.y;
var probeGroup = GetComponent<LightProbeGroup>();
probeGroup.probePositions = probeLocations;
}
private void OnValidate()
{
if (GenerateProbeGrid)
{
GenerateProbeGrid = false;
RegenerateProbeGrid();
}
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment