122 lines
3.6 KiB
C#
122 lines
3.6 KiB
C#
using UnityEngine;
|
|
|
|
namespace UMA.Examples
|
|
{
|
|
[ExecuteInEditMode]
|
|
public class BRDFLookupTexture : MonoBehaviour
|
|
{
|
|
public float intensity = 1.0f;
|
|
|
|
public float diffuseIntensity = 1.0f;
|
|
public Color keyColor = ColorRGB (188, 158, 118);
|
|
public Color fillColor = ColorRGB (86, 91, 108);
|
|
public Color backColor = ColorRGB (44, 54, 57);
|
|
public float wrapAround = 0.0f;
|
|
public float metalic = 0.0f;
|
|
|
|
public float specularIntensity = 1.0f;
|
|
public float specularShininess = 0.078125f;
|
|
|
|
public float translucency = 0.0f; // skin
|
|
public Color translucentColor = ColorRGB (255, 82, 82);
|
|
|
|
public int lookupTextureWidth = 128;
|
|
public int lookupTextureHeight = 128;
|
|
|
|
public bool fastPreview = true;
|
|
|
|
public Texture2D lookupTexture;
|
|
|
|
void Awake () {
|
|
if (!lookupTexture)
|
|
Bake ();
|
|
}
|
|
|
|
static Color ColorRGB (int r, int g, int b) {
|
|
return new Color ((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 0.0f);
|
|
}
|
|
|
|
void CheckConsistency () {
|
|
intensity = Mathf.Max (0.0f, intensity);
|
|
|
|
wrapAround = Mathf.Clamp (wrapAround, -1.0f, 1.0f);
|
|
metalic = Mathf.Clamp (metalic, 0.0f, 12.0f);
|
|
|
|
diffuseIntensity = Mathf.Max (0.0f, diffuseIntensity);
|
|
specularIntensity = Mathf.Max (0.0f, specularIntensity);
|
|
specularShininess = Mathf.Clamp (specularShininess, 0.01f, 1.0f);
|
|
|
|
translucency = Mathf.Clamp01 (translucency);
|
|
}
|
|
|
|
Color PixelFunc (float ndotl, float ndoth)
|
|
{
|
|
// pseudo metalic falloff
|
|
ndotl *= Mathf.Pow (ndoth, metalic);
|
|
float modDiffuseIntensity = (1f + metalic * 0.25f) * Mathf.Max (0f, diffuseIntensity - (1f-ndoth) * metalic);
|
|
|
|
// diffuse tri-light
|
|
float t0 = Mathf.Clamp01 (Mathf.InverseLerp (-wrapAround, 1f, ndotl * 2f - 1f));
|
|
float t1 = Mathf.Clamp01 (Mathf.InverseLerp (-1f, Mathf.Max(-0.99f,-wrapAround), ndotl * 2f - 1f));
|
|
Color diffuse = modDiffuseIntensity * Color.Lerp (backColor, Color.Lerp (fillColor, keyColor, t0), t1);
|
|
diffuse += backColor * (1f - modDiffuseIntensity) * Mathf.Clamp01 (diffuseIntensity);
|
|
|
|
// Blinn-Phong specular (with energy conservation)
|
|
float n = specularShininess * 128f;
|
|
float energyConservationTerm = ((n + 2f)*(n + 4f)) / (8f * Mathf.PI * (Mathf.Pow (2f, -n/2f) + n)); // by ryg
|
|
//float energyConservationTerm = (n + 8f) / (8f * Mathf.PI); // from Real-Time Rendering
|
|
float specular = specularIntensity * energyConservationTerm * Mathf.Pow (ndoth, n);
|
|
|
|
// pseudo translucency (view dependent)
|
|
float a = ndotl + 0.1f;
|
|
float t = 0.5f * translucency * Mathf.Clamp01 (1f-a*ndoth) * Mathf.Clamp01 (1f-ndotl);
|
|
|
|
Color c = diffuse * intensity + translucentColor * t + new Color(0f,0f,0f, specular);
|
|
return c * intensity;
|
|
|
|
}
|
|
|
|
void TextureFunc (Texture2D tex)
|
|
{
|
|
for (int y = 0; y < tex.height; ++y)
|
|
for (int x = 0; x < tex.width; ++x)
|
|
{
|
|
float w = tex.width;
|
|
float h = tex.height;
|
|
float vx = x / w;
|
|
float vy = y / h;
|
|
|
|
float NdotL = vx;
|
|
float NdotH = vy;
|
|
Color c = PixelFunc (NdotL, NdotH);
|
|
tex.SetPixel(x, y, c);
|
|
}
|
|
}
|
|
|
|
void GenerateLookupTexture (int width, int height) {
|
|
Texture2D tex;
|
|
if (lookupTexture && lookupTexture.width == width && lookupTexture.height == height)
|
|
tex = lookupTexture;
|
|
else
|
|
tex = new Texture2D(width, height, TextureFormat.ARGB32, false);
|
|
|
|
CheckConsistency ();
|
|
TextureFunc (tex);
|
|
tex.Apply();
|
|
tex.wrapMode = TextureWrapMode.Clamp;
|
|
|
|
if (lookupTexture != tex)
|
|
DestroyImmediate (lookupTexture);
|
|
lookupTexture = tex;
|
|
}
|
|
|
|
public void Preview () {
|
|
GenerateLookupTexture (32, 64);
|
|
}
|
|
|
|
public void Bake () {
|
|
GenerateLookupTexture (lookupTextureWidth, lookupTextureHeight);
|
|
}
|
|
}
|
|
}
|