mirror of
https://github.com/maxartz15/VolumetricLighting.git
synced 2025-06-19 18:06:44 +02:00
Added the project.
This commit is contained in:
9
Assets/TubeLight/Editor.meta
Normal file
9
Assets/TubeLight/Editor.meta
Normal file
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95f79d7423b1c4239ba221be74ca9134
|
||||
folderAsset: yes
|
||||
timeCreated: 1446582841
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
62
Assets/TubeLight/Editor/TubeLightEditor.cs
Normal file
62
Assets/TubeLight/Editor/TubeLightEditor.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AnimatedValues;
|
||||
|
||||
[CustomEditor(typeof(TubeLight))]
|
||||
[CanEditMultipleObjects]
|
||||
public class TubeLightEditor : Editor {
|
||||
|
||||
AnimFloat m_ShowInfo;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
m_ShowInfo = new AnimFloat(0);
|
||||
m_ShowInfo.valueChanged.AddListener(Repaint);
|
||||
m_ShowInfo.speed = 0.5f;
|
||||
}
|
||||
|
||||
override public void OnInspectorGUI()
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
|
||||
if (targets.Length > 1)
|
||||
return;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if(GUILayout.Button("Add a shadow plane"))
|
||||
m_ShowInfo.value = AddShadowPlane() ? 0 : 100;
|
||||
|
||||
foreach (TubeLightShadowPlane shadowPlane in ((TubeLight)target).m_ShadowPlanes)
|
||||
if (shadowPlane != null)
|
||||
EditorGUILayout.ObjectField("Shadow Plane", shadowPlane, typeof(TubeLightShadowPlane), !EditorUtility.IsPersistent(target));
|
||||
|
||||
m_ShowInfo.target = 0;
|
||||
if (EditorGUILayout.BeginFadeGroup(Mathf.Min(1.0f, m_ShowInfo.value)))
|
||||
EditorGUILayout.HelpBox("Limit of " + TubeLight.maxPlanes + " planes reached. Delete an existing one.", MessageType.Info);
|
||||
EditorGUILayout.EndFadeGroup();
|
||||
}
|
||||
|
||||
bool AddShadowPlane()
|
||||
{
|
||||
TubeLight tubeLight = (TubeLight)target;
|
||||
|
||||
int i = 0;
|
||||
for (; i < TubeLight.maxPlanes; i++)
|
||||
{
|
||||
if (tubeLight.m_ShadowPlanes[i] != null)
|
||||
continue;
|
||||
|
||||
GameObject go = new GameObject("Shadow Plane");
|
||||
TubeLightShadowPlane shadowPlane = go.AddComponent<TubeLightShadowPlane>();
|
||||
|
||||
go.transform.position = tubeLight.transform.position + go.transform.forward;
|
||||
go.transform.parent = tubeLight.transform;
|
||||
tubeLight.m_ShadowPlanes[i] = shadowPlane;
|
||||
EditorUtility.SetDirty (tubeLight);
|
||||
break;
|
||||
}
|
||||
|
||||
return i < TubeLight.maxPlanes;
|
||||
}
|
||||
}
|
12
Assets/TubeLight/Editor/TubeLightEditor.cs.meta
Normal file
12
Assets/TubeLight/Editor/TubeLightEditor.cs.meta
Normal file
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00a6ee99a4a9a44879507a5c4077d7a0
|
||||
timeCreated: 1446582855
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
9
Assets/TubeLight/Scripts.meta
Normal file
9
Assets/TubeLight/Scripts.meta
Normal file
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fa6f2ae72d2fc9643afe34db34a35a28
|
||||
folderAsset: yes
|
||||
timeCreated: 1477748611
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
327
Assets/TubeLight/Scripts/TubeLight.cs
Normal file
327
Assets/TubeLight/Scripts/TubeLight.cs
Normal file
@ -0,0 +1,327 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using System.Collections.Generic;
|
||||
|
||||
[ExecuteInEditMode]
|
||||
public class TubeLight : MonoBehaviour
|
||||
{
|
||||
public float m_Intensity = 0.8f;
|
||||
public Color m_Color = Color.white;
|
||||
public float m_Range = 10.0f;
|
||||
public float m_Radius = 0.3f;
|
||||
public float m_Length = 0.0f;
|
||||
|
||||
[HideInInspector]
|
||||
public Mesh m_Sphere;
|
||||
[HideInInspector]
|
||||
public Mesh m_Capsule;
|
||||
[HideInInspector]
|
||||
public Shader m_ProxyShader;
|
||||
Material m_ProxyMaterial;
|
||||
|
||||
public bool m_RenderSource = false;
|
||||
Renderer m_SourceRenderer;
|
||||
Transform m_SourceTransform;
|
||||
Mesh m_SourceMesh;
|
||||
float m_LastLength = -1;
|
||||
|
||||
public const int maxPlanes = 2;
|
||||
[HideInInspector]
|
||||
public TubeLightShadowPlane[] m_ShadowPlanes = new TubeLightShadowPlane[maxPlanes];
|
||||
|
||||
bool m_Initialized = false;
|
||||
MaterialPropertyBlock m_props;
|
||||
|
||||
const float kMinRadius = 0.001f;
|
||||
bool renderSource {get{return m_RenderSource && m_Radius >= kMinRadius;}}
|
||||
|
||||
Dictionary<Camera, CommandBuffer> m_Cameras = new Dictionary<Camera, CommandBuffer>();
|
||||
static CameraEvent kCameraEvent = CameraEvent.AfterLighting;
|
||||
|
||||
void Start()
|
||||
{
|
||||
if(!Init())
|
||||
return;
|
||||
UpdateMeshesAndBounds();
|
||||
}
|
||||
|
||||
bool Init()
|
||||
{
|
||||
if (m_Initialized)
|
||||
return true;
|
||||
|
||||
// Sometimes on editor startup (especially after project upgrade?), Init() gets called
|
||||
// while m_ProxyShader, m_Sphere or m_Capsule is still null/hasn't loaded.
|
||||
if (m_ProxyShader == null || m_Sphere == null || m_Capsule == null)
|
||||
return false;
|
||||
|
||||
// Proxy
|
||||
m_ProxyMaterial = new Material(m_ProxyShader);
|
||||
m_ProxyMaterial.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
// Source
|
||||
m_SourceMesh = Instantiate<Mesh>(m_Capsule);
|
||||
m_SourceMesh.hideFlags = HideFlags.HideAndDontSave;
|
||||
|
||||
// Can't create the MeshFilter here, since for some reason the DontSave flag has
|
||||
// no effect on it. Has to be added to the prefab instead.
|
||||
//m_SourceMeshFilter = gameObject.AddComponent<MeshFilter>();
|
||||
MeshFilter mfs = gameObject.GetComponent<MeshFilter>();
|
||||
// Hmm, causes trouble
|
||||
// mfs.hideFlags = HideFlags.HideInInspector;
|
||||
mfs.sharedMesh = m_SourceMesh;
|
||||
|
||||
// A similar problem here.
|
||||
// m_SourceRenderer = gameObject.AddComponent<MeshRenderer>();
|
||||
m_SourceRenderer = gameObject.GetComponent<MeshRenderer>();
|
||||
m_SourceRenderer.enabled = true;
|
||||
|
||||
// We want it to be pickable in the scene view, so no HideAndDontSave
|
||||
// Hmm, causes trouble
|
||||
// m_SourceRenderer.hideFlags = HideFlags.DontSave | HideFlags.HideInInspector;
|
||||
|
||||
m_SourceTransform = transform;
|
||||
|
||||
m_Initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if(m_props == null)
|
||||
m_props = new MaterialPropertyBlock();
|
||||
|
||||
if(!Init())
|
||||
return;
|
||||
UpdateMeshesAndBounds();
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
if(!Application.isPlaying)
|
||||
Cleanup();
|
||||
else
|
||||
for(var e = m_Cameras.GetEnumerator(); e.MoveNext();)
|
||||
if(e.Current.Value != null)
|
||||
e.Current.Value.Clear();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (m_ProxyMaterial != null)
|
||||
DestroyImmediate(m_ProxyMaterial);
|
||||
if (m_SourceMesh != null)
|
||||
DestroyImmediate(m_SourceMesh);
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
for(var e = m_Cameras.GetEnumerator(); e.MoveNext();)
|
||||
{
|
||||
var cam = e.Current;
|
||||
if(cam.Key != null && cam.Value != null)
|
||||
cam.Key.RemoveCommandBuffer (kCameraEvent, cam.Value);
|
||||
}
|
||||
m_Cameras.Clear();
|
||||
}
|
||||
|
||||
void UpdateMeshesAndBounds()
|
||||
{
|
||||
// Sanitize
|
||||
m_Range = Mathf.Max(m_Range, 0);
|
||||
m_Radius = Mathf.Max(m_Radius, 0);
|
||||
m_Length = Mathf.Max(m_Length, 0);
|
||||
m_Intensity = Mathf.Max(m_Intensity, 0);
|
||||
|
||||
Vector3 sourceSize = renderSource ? Vector3.one * m_Radius * 2.0f : Vector3.one;
|
||||
if (m_SourceTransform.localScale != sourceSize || m_Length != m_LastLength)
|
||||
{
|
||||
m_LastLength = m_Length;
|
||||
|
||||
Vector3[] vertices = m_Capsule.vertices;
|
||||
for (int i = 0; i < vertices.Length; i++)
|
||||
{
|
||||
if (renderSource)
|
||||
vertices[i].y += Mathf.Sign(vertices[i].y) * (- 0.5f + 0.25f * m_Length / m_Radius);
|
||||
else
|
||||
vertices[i] = Vector3.one * 0.0001f;
|
||||
}
|
||||
|
||||
m_SourceMesh.vertices = vertices;
|
||||
}
|
||||
|
||||
m_SourceTransform.localScale = sourceSize;
|
||||
|
||||
float range = m_Range + m_Radius;
|
||||
|
||||
// TODO: lazy for now, should draw a tight capsule
|
||||
range += 0.5f * m_Length;
|
||||
range *= 1.02f;
|
||||
|
||||
range /= m_Radius;
|
||||
|
||||
m_SourceMesh.bounds = new Bounds(Vector3.zero, Vector3.one * range);
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if(!Init())
|
||||
return;
|
||||
|
||||
UpdateMeshesAndBounds();
|
||||
|
||||
if(Application.isPlaying)
|
||||
for(var e = m_Cameras.GetEnumerator(); e.MoveNext();)
|
||||
if(e.Current.Value != null)
|
||||
e.Current.Value.Clear();
|
||||
}
|
||||
|
||||
Color GetColor()
|
||||
{
|
||||
if (QualitySettings.activeColorSpace == ColorSpace.Gamma)
|
||||
return m_Color * m_Intensity;
|
||||
|
||||
return new Color(
|
||||
Mathf.GammaToLinearSpace(m_Color.r * m_Intensity),
|
||||
Mathf.GammaToLinearSpace(m_Color.g * m_Intensity),
|
||||
Mathf.GammaToLinearSpace(m_Color.b * m_Intensity),
|
||||
1.0f
|
||||
);
|
||||
}
|
||||
|
||||
void OnWillRenderObject()
|
||||
{
|
||||
if(InsideShadowmapCameraRender())
|
||||
return;
|
||||
|
||||
if(!Init())
|
||||
return;
|
||||
|
||||
// TODO: This is just a very rough guess. Need to properly calculate the surface emission
|
||||
// intensity based on light's intensity.
|
||||
m_props.SetVector("_EmissionColor", m_Color * Mathf.Sqrt(m_Intensity) * 2.0f);
|
||||
m_SourceRenderer.SetPropertyBlock(m_props);
|
||||
|
||||
SetUpCommandBuffer();
|
||||
}
|
||||
|
||||
void SetUpCommandBuffer()
|
||||
{
|
||||
Camera cam = Camera.current;
|
||||
CommandBuffer buf = null;
|
||||
if (!m_Cameras.ContainsKey(cam))
|
||||
{
|
||||
buf = new CommandBuffer();
|
||||
buf.name = gameObject.name;
|
||||
m_Cameras[cam] = buf;
|
||||
cam.AddCommandBuffer(kCameraEvent, buf);
|
||||
cam.depthTextureMode |= DepthTextureMode.Depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = m_Cameras[cam];
|
||||
buf.Clear();
|
||||
}
|
||||
|
||||
Transform t = transform;
|
||||
Vector3 lightAxis = t.up;
|
||||
Vector3 lightPos = t.position - 0.5f * lightAxis * m_Length;
|
||||
buf.SetGlobalVector("_LightPos", new Vector4(lightPos.x, lightPos.y, lightPos.z, 1.0f/(m_Range*m_Range)));
|
||||
buf.SetGlobalVector("_LightAxis", new Vector4(lightAxis.x, lightAxis.y, lightAxis.z, 0.0f));
|
||||
buf.SetGlobalFloat("_LightAsQuad", 0);
|
||||
buf.SetGlobalFloat("_LightRadius", m_Radius);
|
||||
buf.SetGlobalFloat("_LightLength", m_Length);
|
||||
buf.SetGlobalVector("_LightColor", GetColor());
|
||||
|
||||
SetShadowPlaneVectors(buf);
|
||||
|
||||
float range = m_Range + m_Radius;
|
||||
// TODO: lazy for now, should draw a tight capsule
|
||||
range += 0.5f * m_Length;
|
||||
range *= 1.02f;
|
||||
range /= m_Radius;
|
||||
|
||||
Matrix4x4 m = Matrix4x4.Scale(Vector3.one * range);
|
||||
buf.DrawMesh(m_Sphere, t.localToWorldMatrix * m, m_ProxyMaterial, 0, 0);
|
||||
}
|
||||
|
||||
public TubeLightShadowPlane.Params[] GetShadowPlaneParams(ref TubeLightShadowPlane.Params[] p)
|
||||
{
|
||||
if (p == null || p.Length != maxPlanes)
|
||||
p = new TubeLightShadowPlane.Params[maxPlanes];
|
||||
for(int i = 0; i < maxPlanes; i++)
|
||||
{
|
||||
TubeLightShadowPlane sp = m_ShadowPlanes[i];
|
||||
p[i].plane = sp == null ? new Vector4(0, 0, 0, 1) : sp.GetShadowPlaneVector();
|
||||
p[i].feather = sp == null ? 1 : sp.feather;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
TubeLightShadowPlane.Params[] sppArr = new TubeLightShadowPlane.Params[maxPlanes];
|
||||
|
||||
void SetShadowPlaneVectors(CommandBuffer buf)
|
||||
{
|
||||
var p = GetShadowPlaneParams(ref sppArr);
|
||||
|
||||
for (int i = 0, n = p.Length; i < n; ++i)
|
||||
{
|
||||
var spp = p[i];
|
||||
if(i == 0) {
|
||||
buf.SetGlobalVector("_ShadowPlane0", spp.plane);
|
||||
buf.SetGlobalFloat("_ShadowPlaneFeather0", spp.feather);
|
||||
} else if(i == 1) {
|
||||
buf.SetGlobalVector("_ShadowPlane1", spp.plane);
|
||||
buf.SetGlobalFloat("_ShadowPlaneFeather1", spp.feather);
|
||||
} else {
|
||||
buf.SetGlobalVector("_ShadowPlane" + i, spp.plane);
|
||||
buf.SetGlobalFloat("_ShadowPlaneFeather" + i, spp.feather);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
if (m_SourceTransform == null)
|
||||
return;
|
||||
|
||||
Gizmos.color = Color.white;
|
||||
// Skip the scale
|
||||
Matrix4x4 m = new Matrix4x4();
|
||||
m.SetTRS(m_SourceTransform.position, m_SourceTransform.rotation, Vector3.one);
|
||||
Gizmos.matrix = m;
|
||||
|
||||
Gizmos.DrawWireSphere(Vector3.zero, m_Radius + m_Range + 0.5f * m_Length);
|
||||
|
||||
Vector3 start = 0.5f * Vector3.up * m_Length;
|
||||
Gizmos.DrawWireSphere(start, m_Radius);
|
||||
|
||||
if (m_Length == 0.0f)
|
||||
return;
|
||||
|
||||
Vector3 end = - 0.5f * Vector3.up * m_Length;
|
||||
Gizmos.DrawWireSphere(end, m_Radius);
|
||||
|
||||
Vector3 r = Vector3.forward * m_Radius;
|
||||
Gizmos.DrawLine(start + r, end + r);
|
||||
Gizmos.DrawLine(start - r, end - r);
|
||||
|
||||
r = Vector3.right * m_Radius;
|
||||
Gizmos.DrawLine(start + r, end + r);
|
||||
Gizmos.DrawLine(start - r, end - r);
|
||||
|
||||
}
|
||||
|
||||
void OnDrawGizmos()
|
||||
{
|
||||
// TODO: Looks like this changed the name. Find a more robust way to use the icon.
|
||||
// Gizmos.DrawIcon(transform.position, "PointLight Gizmo_MIP0.png", true);
|
||||
}
|
||||
|
||||
bool InsideShadowmapCameraRender()
|
||||
{
|
||||
RenderTexture target = Camera.current.targetTexture;
|
||||
return target != null && target.format == RenderTextureFormat.Shadowmap;
|
||||
}
|
||||
}
|
16
Assets/TubeLight/Scripts/TubeLight.cs.meta
Normal file
16
Assets/TubeLight/Scripts/TubeLight.cs.meta
Normal file
@ -0,0 +1,16 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a3b99ed98424ea4587ec18d930a1d77
|
||||
timeCreated: 1444638222
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Sphere: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
|
||||
- m_Capsule: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
|
||||
- m_ProxyShader: {fileID: 4800000, guid: 2e6fd90941a3e3c458d01f851dca21ed, type: 3}
|
||||
- m_SourceShader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
32
Assets/TubeLight/Scripts/TubeLightShadowPlane.cs
Normal file
32
Assets/TubeLight/Scripts/TubeLightShadowPlane.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class TubeLightShadowPlane : MonoBehaviour
|
||||
{
|
||||
[MinValue(0)]
|
||||
public float m_Feather = 1.0f;
|
||||
|
||||
public float feather {get{ return m_Feather * 0.1f;}}
|
||||
|
||||
public Vector4 GetShadowPlaneVector()
|
||||
{
|
||||
Transform t = transform;
|
||||
Vector3 v = t.forward;
|
||||
float d = Vector3.Dot(t.position, v);
|
||||
return new Vector4(v.x, v.y, v.z, d);
|
||||
}
|
||||
|
||||
void OnDrawGizmosSelected()
|
||||
{
|
||||
Matrix4x4 m = Matrix4x4.zero;
|
||||
Transform t = transform;
|
||||
m.SetTRS(t.position, t.rotation, new Vector3(1, 1, 0));
|
||||
Gizmos.matrix = m;
|
||||
Gizmos.DrawWireSphere(Vector3.zero, 1);
|
||||
}
|
||||
|
||||
public struct Params
|
||||
{
|
||||
public Vector4 plane;
|
||||
public float feather;
|
||||
}
|
||||
}
|
12
Assets/TubeLight/Scripts/TubeLightShadowPlane.cs.meta
Normal file
12
Assets/TubeLight/Scripts/TubeLightShadowPlane.cs.meta
Normal file
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66d8e50a047abb54aa901236f0ed84d2
|
||||
timeCreated: 1446129202
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
9
Assets/TubeLight/Shaders.meta
Normal file
9
Assets/TubeLight/Shaders.meta
Normal file
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b041de53e70b28e4fb9256c930c13615
|
||||
folderAsset: yes
|
||||
timeCreated: 1477749221
|
||||
licenseType: Pro
|
||||
DefaultImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
189
Assets/TubeLight/Shaders/TubeLight.cginc
Normal file
189
Assets/TubeLight/Shaders/TubeLight.cginc
Normal file
@ -0,0 +1,189 @@
|
||||
// Based on 'Real Shading in Unreal Engine 4'
|
||||
// http://blog.selfshadow.com/publications/s2013-shading-course/#course_content
|
||||
|
||||
#include "TubeLightAttenuation.cginc"
|
||||
|
||||
#ifndef SHADOW_PLANES
|
||||
#define SHADOW_PLANES 1
|
||||
#endif
|
||||
|
||||
#if SHADOW_PLANES
|
||||
#include "TubeLightShadowPlanes.cginc"
|
||||
#endif
|
||||
|
||||
#define SHARP_EDGE_FIX 1
|
||||
|
||||
void SphereLightToPointLight(float3 pos, float3 lightPos, float3 eyeVec, half3 normal, float sphereRad, half rangeSqInv, inout UnityLight light, out half lightDist)
|
||||
{
|
||||
half3 viewDir = -eyeVec;
|
||||
half3 r = reflect (viewDir, normal);
|
||||
|
||||
float3 L = lightPos - pos;
|
||||
float3 centerToRay = dot (L, r) * r - L;
|
||||
float3 closestPoint = L + centerToRay * saturate(sphereRad / length(centerToRay));
|
||||
|
||||
lightDist = length(closestPoint);
|
||||
light.dir = closestPoint / lightDist;
|
||||
|
||||
half distLSq = dot(L, L);
|
||||
light.ndotl = saturate(dot(normal, L/sqrt(distLSq)));
|
||||
|
||||
float distNorm = distLSq * rangeSqInv;
|
||||
float atten = AttenuationToZero(distNorm);
|
||||
light.color *= atten;
|
||||
}
|
||||
|
||||
void TubeLightToPointLight(float3 pos, float3 tubeStart, float3 tubeEnd, float3 normal, float tubeRad, float rangeSqInv, float3 representativeDir, float3 lightColor, out float3 outLightColor, out float3 outLightDir, out float outNdotL, out half outLightDist)
|
||||
{
|
||||
half3 N = normal;
|
||||
float3 L0 = tubeStart - pos;
|
||||
float3 L1 = tubeEnd - pos;
|
||||
float L0dotL0 = dot(L0, L0);
|
||||
float distL0 = sqrt(L0dotL0);
|
||||
float distL1 = length(L1);
|
||||
|
||||
float NdotL0 = dot(L0, N) / (2.0 * distL0);
|
||||
float NdotL1 = dot(L1, N) / (2.0 * distL1);
|
||||
outNdotL = saturate(NdotL0 + NdotL1);
|
||||
|
||||
float3 Ldir = L1 - L0;
|
||||
float RepdotL0 = dot(representativeDir, L0);
|
||||
float RepdotLdir = dot(representativeDir, Ldir);
|
||||
float L0dotLdir = dot(L0, Ldir);
|
||||
float LdirdotLdir = dot(Ldir, Ldir);
|
||||
float distLdir = sqrt(LdirdotLdir);
|
||||
|
||||
#if SHARP_EDGE_FIX
|
||||
// There's a very visible discontinuity if we just take the closest distance to ray,
|
||||
// as the original paper suggests. This is an attempt to fix it, but it gets slightly more expensive and
|
||||
// has its own artifact, although this time at least C0 smooth.
|
||||
|
||||
// Smallest angle to ray
|
||||
float t = (L0dotLdir * RepdotL0 - L0dotL0 * RepdotLdir) / (L0dotLdir * RepdotLdir - LdirdotLdir * RepdotL0);
|
||||
t = saturate(t);
|
||||
|
||||
// As representativeDir becomes parallel (well, in some plane) to Ldir and then points away, t flips from 0 to 1 (or vv) and a discontinuity shows up.
|
||||
// Counteract by detecting that relative angle/position and flip t. The discontinuity in t moves to the back side.
|
||||
float3 L0xLdir = cross(L0, Ldir);
|
||||
float3 LdirxR = cross(Ldir, representativeDir);
|
||||
float RepAtLdir = dot(L0xLdir, LdirxR);
|
||||
|
||||
// RepAtLdir is negative if R points away from Ldir.
|
||||
// TODO: check if lerp below is indeed cheaper.
|
||||
// if (RepAtLdir < 0)
|
||||
// t = 1 - t;
|
||||
t = lerp(1 - t, t, step(0, RepAtLdir));
|
||||
|
||||
#else
|
||||
// Original by Karis
|
||||
// Closest distance to ray
|
||||
float t = (RepdotL0 * RepdotLdir - L0dotLdir) / (distLdir * distLdir - RepdotLdir * RepdotLdir);
|
||||
t = saturate(t);
|
||||
|
||||
#endif
|
||||
|
||||
float3 closestPoint = L0 + Ldir * t;
|
||||
float3 centerToRay = dot(closestPoint, representativeDir) * representativeDir - closestPoint;
|
||||
|
||||
closestPoint = closestPoint + centerToRay * saturate(tubeRad / length(centerToRay));
|
||||
|
||||
outLightDist = length(closestPoint);
|
||||
outLightDir = closestPoint / outLightDist;
|
||||
|
||||
float distNorm = 0.5f * (distL0 * distL1 + dot(L0, L1)) * rangeSqInv;
|
||||
outLightColor = lightColor * AttenuationToZero(distNorm);
|
||||
}
|
||||
|
||||
void TubeLightToPointLight(float3 pos, float3 tubeStart, float3 tubeEnd, float3 eyeVec, float3 normal, float tubeRad, float rangeSqInv, float3 lightColor, out float3 outLightColor, out float3 outLightDir, out float outNdotL, out half outLightDist)
|
||||
{
|
||||
half3 viewDir = -eyeVec;
|
||||
half3 representativeDir = reflect (viewDir, normal);
|
||||
|
||||
TubeLightToPointLight(pos, tubeStart, tubeEnd, normal, tubeRad, rangeSqInv, representativeDir, lightColor, outLightColor, outLightDir, outNdotL, outLightDist);
|
||||
}
|
||||
|
||||
inline half GGXTerm_Area (half NdotH, half roughness, half lightDist, half lightRadius)
|
||||
{
|
||||
half a = roughness * roughness;
|
||||
half a2 = a * a;
|
||||
half d = NdotH * NdotH * (a2 - 1.f) + 1.f;
|
||||
d = max(d, 0.000001);
|
||||
|
||||
half aP = saturate( lightRadius / (lightDist*2.0) + a);
|
||||
half aP2 = aP * aP;
|
||||
|
||||
return a2 * a2 / (UNITY_PI * d * d * aP2);
|
||||
}
|
||||
|
||||
half4 BRDF1_Unity_PBS_Area (half3 diffColor, half3 specColor, half oneMinusReflectivity, half oneMinusRoughness,
|
||||
half3 normal, half3 viewDir,
|
||||
UnityLight light, UnityIndirect gi, half lightDist, half lightRadius)
|
||||
{
|
||||
half roughness = 1-oneMinusRoughness;
|
||||
half3 halfDir = Unity_SafeNormalize (light.dir + viewDir);
|
||||
|
||||
half nl = light.ndotl;
|
||||
half nh = BlinnTerm (normal, halfDir);
|
||||
half nv = DotClamped (normal, viewDir);
|
||||
half lv = DotClamped (light.dir, viewDir);
|
||||
half lh = DotClamped (light.dir, halfDir);
|
||||
|
||||
half V = SmithGGXVisibilityTerm (nl, nv, roughness);
|
||||
half D = GGXTerm_Area (nh, roughness, lightDist, lightRadius);
|
||||
|
||||
half nlPow5 = Pow5 (1-nl);
|
||||
half nvPow5 = Pow5 (1-nv);
|
||||
half Fd90 = 0.5 + 2 * lh * lh * roughness;
|
||||
half disneyDiffuse = (1 + (Fd90-1) * nlPow5) * (1 + (Fd90-1) * nvPow5);
|
||||
|
||||
// HACK: theoretically we should divide by Pi diffuseTerm and not multiply specularTerm!
|
||||
// BUT 1) that will make shader look significantly darker than Legacy ones
|
||||
// and 2) on engine side "Non-important" lights have to be divided by Pi to in cases when they are injected into ambient SH
|
||||
// NOTE: multiplication by Pi is part of single constant together with 1/4 now
|
||||
|
||||
half specularTerm = (V * D) * (UNITY_PI/4); // Torrance-Sparrow model, Fresnel is applied later (for optimization reasons)
|
||||
if (IsGammaSpace())
|
||||
specularTerm = sqrt(max(1e-4h, specularTerm));
|
||||
specularTerm = max(0, specularTerm * nl);
|
||||
half diffuseTerm = disneyDiffuse * nl;
|
||||
|
||||
half grazingTerm = saturate(oneMinusRoughness + (1-oneMinusReflectivity));
|
||||
half3 color = diffColor * (gi.diffuse + light.color * diffuseTerm)
|
||||
+ specularTerm * light.color * FresnelTerm (specColor, lh)
|
||||
+ gi.specular * FresnelLerp (specColor, grazingTerm, nv);
|
||||
|
||||
return half4(color, 1);
|
||||
}
|
||||
|
||||
half4 CalculateLight (float3 worldPos, float2 uv, half3 baseColor, half3 specColor, half oneMinusRoughness, half3 normalWorld,
|
||||
half3 lightStart, half3 lightEnd, half3 lightColor, half lightRadius, half lightRangeSqInv)
|
||||
{
|
||||
UnityLight light = (UnityLight)0;
|
||||
|
||||
float3 eyeVec = normalize(worldPos - _WorldSpaceCameraPos);
|
||||
half lightDist = 0;
|
||||
|
||||
#if 0
|
||||
// Can't use a keyword, because no keywords in material property blocks.
|
||||
// TODO: is it worth the dynamic branch?
|
||||
if (sphereLight)
|
||||
SphereLightToPointLight (worldPos, lightStart, eyeVec, normalWorld, lightRadius, lightRangeSqInv, light, lightDist);
|
||||
else
|
||||
#else
|
||||
TubeLightToPointLight (worldPos, lightStart, lightEnd, eyeVec, normalWorld, lightRadius, lightRangeSqInv, lightColor, light.color, light.dir, light.ndotl, lightDist);
|
||||
#endif
|
||||
|
||||
#if SHADOW_PLANES
|
||||
light.color *= ShadowPlanes(worldPos);
|
||||
#endif
|
||||
|
||||
half oneMinusReflectivity = 1 - SpecularStrength(specColor.rgb);
|
||||
|
||||
UnityIndirect ind;
|
||||
UNITY_INITIALIZE_OUTPUT(UnityIndirect, ind);
|
||||
ind.diffuse = 0;
|
||||
ind.specular = 0;
|
||||
|
||||
half4 res = BRDF1_Unity_PBS_Area (baseColor, specColor, oneMinusReflectivity, oneMinusRoughness, normalWorld, -eyeVec, light, ind, lightDist, lightRadius);
|
||||
return res;
|
||||
}
|
9
Assets/TubeLight/Shaders/TubeLight.cginc.meta
Normal file
9
Assets/TubeLight/Shaders/TubeLight.cginc.meta
Normal file
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bea54fea6aabea841b90651d989d88f5
|
||||
timeCreated: 1452380090
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
87
Assets/TubeLight/Shaders/TubeLight.shader
Normal file
87
Assets/TubeLight/Shaders/TubeLight.shader
Normal file
@ -0,0 +1,87 @@
|
||||
Shader "Hidden/TubeLight" {
|
||||
SubShader {
|
||||
Tags { "Queue"="Geometry-1" }
|
||||
|
||||
CGINCLUDE
|
||||
#include "UnityCG.cginc"
|
||||
#include "UnityPBSLighting.cginc"
|
||||
#include "UnityDeferredLibrary.cginc"
|
||||
|
||||
#define SHADOW_PLANES 1
|
||||
#include "TubeLight.cginc"
|
||||
|
||||
sampler2D _CameraGBufferTexture0;
|
||||
sampler2D _CameraGBufferTexture1;
|
||||
sampler2D _CameraGBufferTexture2;
|
||||
|
||||
float _LightRadius;
|
||||
float _LightLength;
|
||||
float4 _LightAxis;
|
||||
|
||||
|
||||
void DeferredCalculateLightParams (
|
||||
unity_v2f_deferred i,
|
||||
out float3 outWorldPos,
|
||||
out float2 outUV)
|
||||
{
|
||||
i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
|
||||
float2 uv = i.uv.xy / i.uv.w;
|
||||
|
||||
// read depth and reconstruct world position
|
||||
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
|
||||
depth = Linear01Depth (depth);
|
||||
float4 vpos = float4(i.ray * depth,1);
|
||||
float3 wpos = mul (unity_CameraToWorld, vpos).xyz;
|
||||
|
||||
outWorldPos = wpos;
|
||||
outUV = uv;
|
||||
}
|
||||
|
||||
half4 CalculateLightDeferred (unity_v2f_deferred i)
|
||||
{
|
||||
float3 worldPos;
|
||||
float2 uv;
|
||||
DeferredCalculateLightParams (i, worldPos, uv);
|
||||
|
||||
half4 gbuffer0 = tex2D (_CameraGBufferTexture0, uv);
|
||||
half4 gbuffer1 = tex2D (_CameraGBufferTexture1, uv);
|
||||
half4 gbuffer2 = tex2D (_CameraGBufferTexture2, uv);
|
||||
|
||||
half3 baseColor = gbuffer0.rgb;
|
||||
half3 specColor = gbuffer1.rgb;
|
||||
half oneMinusRoughness = gbuffer1.a;
|
||||
half3 normalWorld = gbuffer2.rgb * 2 - 1;
|
||||
normalWorld = normalize(normalWorld);
|
||||
|
||||
return CalculateLight (worldPos, uv, baseColor, specColor, oneMinusRoughness, normalWorld,
|
||||
_LightPos.xyz, _LightPos.xyz + _LightAxis.xyz * _LightLength, _LightColor.xyz, _LightRadius, _LightPos.w);
|
||||
}
|
||||
ENDCG
|
||||
|
||||
Pass {
|
||||
Fog { Mode Off }
|
||||
ZWrite Off
|
||||
Blend One One
|
||||
Cull Front
|
||||
ZTest Always
|
||||
|
||||
|
||||
CGPROGRAM
|
||||
#pragma target 3.0
|
||||
#pragma vertex vert_deferred
|
||||
#pragma fragment frag
|
||||
#pragma exclude_renderers nomrt
|
||||
|
||||
fixed4 frag (unity_v2f_deferred i) : SV_Target
|
||||
{
|
||||
half4 light = CalculateLightDeferred(i);
|
||||
// TODO: squash those NaNs at their source
|
||||
return isnan(light) ? 0 : light;
|
||||
}
|
||||
|
||||
ENDCG
|
||||
}
|
||||
|
||||
}
|
||||
Fallback Off
|
||||
}
|
9
Assets/TubeLight/Shaders/TubeLight.shader.meta
Normal file
9
Assets/TubeLight/Shaders/TubeLight.shader.meta
Normal file
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e6fd90941a3e3c458d01f851dca21ed
|
||||
timeCreated: 1442344786
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
55
Assets/TubeLight/Shaders/TubeLightAttenuation.cginc
Normal file
55
Assets/TubeLight/Shaders/TubeLightAttenuation.cginc
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef TUBE_LIGHT_ATTENUATION_LEGACY
|
||||
#define TUBE_LIGHT_ATTENUATION_LEGACY 0
|
||||
#endif
|
||||
|
||||
#if TUBE_LIGHT_ATTENUATION_LEGACY
|
||||
|
||||
float Attenuation(float distNorm)
|
||||
{
|
||||
return 1.0 / (1.0 + 25.0 * distNorm);
|
||||
}
|
||||
|
||||
float AttenuationToZero(float distNorm)
|
||||
{
|
||||
float att = Attenuation(distNorm);
|
||||
|
||||
// Replicating unity light attenuation - pulled to 0 at range
|
||||
// if (distNorm > 0.8 * 0.8)
|
||||
// att *= 1 - (distNorm - 0.8 * 0.8) / (1 - 0.8 * 0.8);
|
||||
// Same, simplified
|
||||
float oneDistNorm = 1.0 - distNorm;
|
||||
att *= lerp(1.0, oneDistNorm * 2.78, step(0.64, distNorm));
|
||||
|
||||
att *= step(0.0, oneDistNorm);
|
||||
|
||||
return att;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
float Attenuation(float distSqr)
|
||||
{
|
||||
float d = sqrt(distSqr);
|
||||
float kDefaultPointLightRadius = 0.25;
|
||||
return 1.0 / pow(1.0 + d/kDefaultPointLightRadius, 2);
|
||||
}
|
||||
|
||||
float AttenuationToZero(float distSqr)
|
||||
{
|
||||
// attenuation = 1 / (1 + distance_to_light / light_radius)^2
|
||||
// = 1 / (1 + 2*(d/r) + (d/r)^2)
|
||||
// For more details see: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/
|
||||
float d = sqrt(distSqr);
|
||||
float kDefaultPointLightRadius = 0.25;
|
||||
float atten = 1.0 / pow(1.0 + d/kDefaultPointLightRadius, 2);
|
||||
float kCutoff = 1.0 / pow(1.0 + 1.0/kDefaultPointLightRadius, 2); // cutoff equal to attenuation at distance 1.0
|
||||
|
||||
// Force attenuation to fall towards zero at distance 1.0
|
||||
atten = (atten - kCutoff) / (1.f - kCutoff);
|
||||
if (d >= 1.f)
|
||||
atten = 0.f;
|
||||
|
||||
return atten;
|
||||
}
|
||||
|
||||
#endif
|
9
Assets/TubeLight/Shaders/TubeLightAttenuation.cginc.meta
Normal file
9
Assets/TubeLight/Shaders/TubeLightAttenuation.cginc.meta
Normal file
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d6df6428d576d147994b0b7ac0d5ea5
|
||||
timeCreated: 1456703457
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
38
Assets/TubeLight/Shaders/TubeLightShadowPlanes.cginc
Normal file
38
Assets/TubeLight/Shaders/TubeLightShadowPlanes.cginc
Normal file
@ -0,0 +1,38 @@
|
||||
half ShadowPlane(half3 worldPos, half4 plane, half feather)
|
||||
{
|
||||
half x = plane.w - dot(worldPos, plane.xyz);
|
||||
// Compiler bug workaround
|
||||
x += 0.0001;
|
||||
return smoothstep(-feather, feather, x);
|
||||
}
|
||||
|
||||
float4 _ShadowPlane0;
|
||||
float _ShadowPlaneFeather0;
|
||||
float4 _ShadowPlane1;
|
||||
float _ShadowPlaneFeather1;
|
||||
|
||||
half ShadowPlanes(half3 worldPos)
|
||||
{
|
||||
half att = 1;
|
||||
att *= ShadowPlane(worldPos, _ShadowPlane0, _ShadowPlaneFeather0);
|
||||
att *= ShadowPlane(worldPos, _ShadowPlane1, _ShadowPlaneFeather1);
|
||||
return att;
|
||||
}
|
||||
|
||||
struct TubeLightShadowPlane
|
||||
{
|
||||
float4 plane0;
|
||||
float4 plane1;
|
||||
float feather0;
|
||||
float feather1;
|
||||
float padding0;
|
||||
float padding1;
|
||||
};
|
||||
|
||||
half ShadowPlanes(half3 worldPos, TubeLightShadowPlane params)
|
||||
{
|
||||
half att = 1;
|
||||
att *= ShadowPlane(worldPos, params.plane0, params.feather0);
|
||||
att *= ShadowPlane(worldPos, params.plane1, params.feather1);
|
||||
return att;
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4ec63bd62722b840b982641528198db
|
||||
timeCreated: 1457385992
|
||||
licenseType: Pro
|
||||
ShaderImporter:
|
||||
defaultTextures: []
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
190
Assets/TubeLight/Shaders/TubeLightSource.mat
Normal file
190
Assets/TubeLight/Shaders/TubeLightSource.mat
Normal file
@ -0,0 +1,190 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 0}
|
||||
m_Name: TubeLightSource
|
||||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ShaderKeywords: _EMISSION
|
||||
m_LightmapFlags: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
m_SavedProperties:
|
||||
serializedVersion: 2
|
||||
m_TexEnvs:
|
||||
- first:
|
||||
name: _BumpMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _DetailAlbedoMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _DetailMask
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _DetailNormalMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _EmissionMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _MainTex
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _MetallicGlossMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _OcclusionMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _ParallaxMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- first:
|
||||
name: _SpecGlossMap
|
||||
second:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- first:
|
||||
name: _BumpScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _CullMode
|
||||
second: 2
|
||||
- first:
|
||||
name: _Cutoff
|
||||
second: 0.5
|
||||
- first:
|
||||
name: _DetailMode
|
||||
second: 0
|
||||
- first:
|
||||
name: _DetailNormalMapScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _DstBlend
|
||||
second: 0
|
||||
- first:
|
||||
name: _GlossMapScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _Glossiness
|
||||
second: 0.234
|
||||
- first:
|
||||
name: _GlossyReflections
|
||||
second: 1
|
||||
- first:
|
||||
name: _LightProbeScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _MetaDiffuseScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _MetaEmissionScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _MetaMetallicSoup
|
||||
second: 1
|
||||
- first:
|
||||
name: _MetaSpecularScale
|
||||
second: 1
|
||||
- first:
|
||||
name: _MetaUseCustom
|
||||
second: 0
|
||||
- first:
|
||||
name: _Metallic
|
||||
second: 0
|
||||
- first:
|
||||
name: _Mode
|
||||
second: 0
|
||||
- first:
|
||||
name: _OcclusionStrength
|
||||
second: 1
|
||||
- first:
|
||||
name: _Parallax
|
||||
second: 0.02
|
||||
- first:
|
||||
name: _ReflectionProbeBoost
|
||||
second: 1
|
||||
- first:
|
||||
name: _SmoothnessTextureChannel
|
||||
second: 0
|
||||
- first:
|
||||
name: _SpecularHighlights
|
||||
second: 1
|
||||
- first:
|
||||
name: _SrcBlend
|
||||
second: 1
|
||||
- first:
|
||||
name: _Translucency
|
||||
second: 0
|
||||
- first:
|
||||
name: _UVDetailMask
|
||||
second: 0
|
||||
- first:
|
||||
name: _UVSec
|
||||
second: 0
|
||||
- first:
|
||||
name: _VertexOcclusionPower
|
||||
second: 1
|
||||
- first:
|
||||
name: _ZWrite
|
||||
second: 1
|
||||
m_Colors:
|
||||
- first:
|
||||
name: _Color
|
||||
second: {r: 0.47794116, g: 1, b: 0.85685486, a: 1}
|
||||
- first:
|
||||
name: _EmissionColor
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
||||
- first:
|
||||
name: _MetaDiffuseAdd
|
||||
second: {r: 0, g: 0, b: 0, a: 1}
|
||||
- first:
|
||||
name: _MetaDiffuseTint
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
||||
- first:
|
||||
name: _MetaEmissionAdd
|
||||
second: {r: 0, g: 0, b: 0, a: 1}
|
||||
- first:
|
||||
name: _MetaEmissionTint
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
||||
- first:
|
||||
name: _MetaSpecularAdd
|
||||
second: {r: 0, g: 0, b: 0, a: 1}
|
||||
- first:
|
||||
name: _MetaSpecularTint
|
||||
second: {r: 1, g: 1, b: 1, a: 1}
|
||||
- first:
|
||||
name: _SpecColor
|
||||
second: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1}
|
8
Assets/TubeLight/Shaders/TubeLightSource.mat.meta
Normal file
8
Assets/TubeLight/Shaders/TubeLightSource.mat.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86b3c638dc56298409890ac32f9e6baf
|
||||
timeCreated: 1446644410
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
180
Assets/TubeLight/TubeLight.prefab
Normal file
180
Assets/TubeLight/TubeLight.prefab
Normal file
@ -0,0 +1,180 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &154090
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
serializedVersion: 4
|
||||
m_Component:
|
||||
- 4: {fileID: 466162}
|
||||
- 114: {fileID: 11466842}
|
||||
- 33: {fileID: 3327276}
|
||||
- 23: {fileID: 2315154}
|
||||
- 114: {fileID: 114000012794840980}
|
||||
m_Layer: 0
|
||||
m_Name: TubeLight
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &466162
|
||||
Transform:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 154090}
|
||||
m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071067}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
--- !u!23 &2315154
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 154090}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 0
|
||||
m_ReceiveShadows: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 0
|
||||
m_ReflectionProbeUsage: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 86b3c638dc56298409890ac32f9e6baf, type: 2}
|
||||
m_SubsetIndices:
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_SelectedWireframeHidden: 0
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
--- !u!33 &3327276
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 154090}
|
||||
m_Mesh: {fileID: 0}
|
||||
--- !u!114 &11466842
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 154090}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5a3b99ed98424ea4587ec18d930a1d77, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Intensity: 0.8
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_Range: 10
|
||||
m_Radius: 0.3
|
||||
m_Length: 0
|
||||
m_Sphere: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_Capsule: {fileID: 10208, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_ProxyShader: {fileID: 4800000, guid: 2e6fd90941a3e3c458d01f851dca21ed, type: 3}
|
||||
m_RenderSource: 1
|
||||
m_ShadowPlanes:
|
||||
- {fileID: 0}
|
||||
- {fileID: 0}
|
||||
--- !u!1001 &100100000
|
||||
Prefab:
|
||||
m_ObjectHideFlags: 1
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_RenderSource
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_Radius
|
||||
value: .340000004
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_Length
|
||||
value: .649999976
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: -.707106829
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: .707106709
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_CastShadows
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_ReceiveShadows
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_UseLightProbes
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_ReflectionProbeUsage
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 0}
|
||||
propertyPath: m_Materials.Array.data[0]
|
||||
value:
|
||||
objectReference: {fileID: 2100000, guid: 86b3c638dc56298409890ac32f9e6baf, type: 2}
|
||||
m_RemovedComponents: []
|
||||
m_ParentPrefab: {fileID: 0}
|
||||
m_RootGameObject: {fileID: 154090}
|
||||
m_IsPrefabParent: 1
|
||||
--- !u!114 &114000012794840980
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_PrefabParentObject: {fileID: 0}
|
||||
m_PrefabInternal: {fileID: 100100000}
|
||||
m_GameObject: {fileID: 154090}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 097385f2a510795498370c4d62e61572, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IntensityMult: 1
|
||||
m_RangeMult: 1
|
||||
m_BlurShadowmapShader: {fileID: 4800000, guid: 701192b62a7678549918bc87434699fe,
|
||||
type: 3}
|
||||
m_CopyShadowParamsShader: {fileID: 4800000, guid: 33fc45db43408764c8dd7647b877e561,
|
||||
type: 3}
|
||||
m_ForceOnForFog: 0
|
||||
m_Shadows: 0
|
||||
m_ShadowmapRes: 256
|
||||
m_BlurIterations: 0
|
||||
m_BlurSize: 1
|
||||
m_ESMExponent: 40
|
||||
m_Bounded: 1
|
8
Assets/TubeLight/TubeLight.prefab.meta
Normal file
8
Assets/TubeLight/TubeLight.prefab.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdeb35bdab08b7442a67e36ffe2ff830
|
||||
timeCreated: 1444651113
|
||||
licenseType: Pro
|
||||
NativeFormatImporter:
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user