Created
March 21, 2024 23:04
-
-
Save pema99/e04be4961f5ee7b5ce2a45b02324af84 to your computer and use it in GitHub Desktop.
Analytical polygonal irradiance
This file contains hidden or 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 System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
[ExecuteAlways] | |
public class QuadLightEmitter : MonoBehaviour | |
{ | |
[ColorUsage(false, true)] | |
public Color color = Color.white; | |
public Transform[] verts; | |
void OnEnable() | |
{ | |
if (verts == null || verts.Length < 4) | |
{ | |
verts = new Transform[4]; | |
for (int i = 0; i < 4; i++) | |
{ | |
verts[i] = transform.GetChild(i); | |
} | |
} | |
} | |
void Update() | |
{ | |
for (int i = 0; i < 4; i++) | |
{ | |
Vector3 vert = verts[i].position; | |
Shader.SetGlobalVector($"_QuadLightVert{i}", vert); | |
Shader.SetGlobalVector("_QuadLightColor", color); | |
} | |
} | |
} |
This file contains hidden or 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
Shader "Unlit/PolygonLight" | |
{ | |
Properties | |
{ | |
_Albedo ("Albedo", Color) = (1, 1, 1, 1) | |
} | |
SubShader | |
{ | |
Tags { "RenderType"="Opaque" } | |
Pass | |
{ | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag | |
#include "UnityCG.cginc" | |
struct appdata | |
{ | |
float4 vertex : POSITION; | |
float2 uv : TEXCOORD0; | |
float3 normal : NORMAL; | |
}; | |
struct v2f | |
{ | |
float2 uv : TEXCOORD0; | |
float4 vertex : SV_POSITION; | |
float3 normal : NORMAL; | |
}; | |
v2f vert (appdata v) | |
{ | |
v2f o; | |
o.vertex = UnityObjectToClipPos(v.vertex); | |
o.uv = v.uv; | |
o.normal = normalize(UnityObjectToWorldNormal(v.normal)); | |
return o; | |
} | |
float3 _QuadLightVert0; | |
float3 _QuadLightVert1; | |
float3 _QuadLightVert2; | |
float3 _QuadLightVert3; | |
float3 _QuadLightColor; | |
float3 _Albedo; | |
float3x3 OrthoBasisFromVector(float3 n) | |
{ | |
float sign = n.z >= 0.0 ? 1.0 : -1.0; | |
const float a = -1.0 / (sign + n.z); | |
const float b = n.x * n.y * a; | |
float3 b1 = float3(1.0 + sign * n.x * n.x * a, sign * b, -sign * n.x); | |
float3 b2 = float3(b, sign + n.y * n.y * a, -n.y); | |
return float3x3(b1, b2, n); | |
} | |
float4 frag (v2f i) : SV_Target | |
{ | |
float3 verts[4] = { _QuadLightVert0, _QuadLightVert1, _QuadLightVert2, _QuadLightVert3 }; | |
float3 worldPos = mul(unity_ObjectToWorld, float4(0, 0, 0, 1)).xyz; | |
float3x3 toTangentSpace = OrthoBasisFromVector(i.normal); | |
float sum = 0.0; | |
for (uint idx = 0; idx < 4; idx++) | |
{ | |
// Transform world space verts into object space coordinates, but dont apply rotation | |
float3 objectSpaceV0 = verts[idx] - worldPos; | |
float3 objectSpaceV1 = verts[(idx + 1) % 4] - worldPos; | |
// Transform object space verts into tangent space | |
float3 v0 = mul(toTangentSpace, normalize(objectSpaceV0)); | |
float3 v1 = mul(toTangentSpace, normalize(objectSpaceV1)); | |
// Calculate analytical contribution to irradiance | |
sum += acos(dot(v0, v1)) * dot(normalize(cross(v0, v1)) , float3(0, 0, 1)); | |
} | |
sum *= 1.0 / (2.0 * 3.14159265359); | |
return float4(sum * _QuadLightColor * saturate(_Albedo), 1); | |
} | |
ENDCG | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment