|
|
|
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using UnityEngine.ScriptableRenderPipeline; |
|
|
|
|
|
|
|
// Very basic scriptable rendering loop example:
|
|
|
|
// - Use with BasicRenderLoopShader.shader (the loop expects "BasicPass" pass type to exist)
|
|
|
|
|
|
|
// - This loop also does not setup lightmaps, light probes, reflection probes or light cookies
|
|
|
|
|
|
|
|
[ExecuteInEditMode] |
|
|
|
public class BasicRenderBatching : RenderPipeline |
|
|
|
public class BasicRenderBatching : RenderPipelineAsset |
|
|
|
|
|
|
|
[UnityEditor.MenuItem("Renderloop/Create BasicRenderBatching")] |
|
|
|
[UnityEditor.MenuItem("RenderPipeline/Create BasicRenderBatching")] |
|
|
|
static void CreateBasicRenderLoop() |
|
|
|
{ |
|
|
|
var instance = ScriptableObject.CreateInstance<BasicRenderBatching>(); |
|
|
|
|
|
|
|
|
|
|
private ShaderPassName shaderPassBasic; |
|
|
|
|
|
|
|
public void OnEnable() |
|
|
|
protected override IRenderPipeline InternalCreatePipeline() |
|
|
|
Rebuild(); |
|
|
|
return new BasicRenderLoopBatchingInstance(); |
|
|
|
} |
|
|
|
public override void Initialize() |
|
|
|
public class BasicRenderLoopBatchingInstance : RenderPipeline |
|
|
|
{ |
|
|
|
|
|
|
|
public override void Render(ScriptableRenderContext renderContext, Camera[] cameras) |
|
|
|
shaderPassBasic = new ShaderPassName("BasicPass"); |
|
|
|
base.Render(renderContext, cameras); |
|
|
|
BasicRenderingBatching.Render(renderContext, cameras); |
|
|
|
} |
|
|
|
public static class BasicRenderingBatching |
|
|
|
{ |
|
|
|
public override void Render(Camera[] cameras, RenderLoop loop) |
|
|
|
|
|
|
|
public static void Render(ScriptableRenderContext context, IEnumerable<Camera> cameras) |
|
|
|
if (!CullResults.GetCullingParameters (camera, out cullingParams)) |
|
|
|
if (!CullResults.GetCullingParameters(camera, out cullingParams)) |
|
|
|
CullResults cull = CullResults.Cull (ref cullingParams, loop); |
|
|
|
CullResults cull = CullResults.Cull(ref cullingParams, context); |
|
|
|
loop.SetupCameraProperties (camera); |
|
|
|
context.SetupCameraProperties(camera); |
|
|
|
loop.ExecuteCommandBuffer(cmd); |
|
|
|
context.ExecuteCommandBuffer(cmd); |
|
|
|
SetupLightShaderVariables (cull.visibleLights, loop); |
|
|
|
SetupLightShaderVariables(cull.visibleLights, context); |
|
|
|
var settings = new DrawRendererSettings (cull, camera, shaderPassBasic); |
|
|
|
var settings = new DrawRendererSettings(cull, camera, new ShaderPassName("BasicPass")); |
|
|
|
settings.inputFilter.SetQueuesOpaque (); |
|
|
|
loop.DrawRenderers (ref settings); |
|
|
|
settings.inputFilter.SetQueuesOpaque(); |
|
|
|
context.DrawRenderers(ref settings); |
|
|
|
loop.DrawSkybox (camera); |
|
|
|
context.DrawSkybox(camera); |
|
|
|
settings.inputFilter.SetQueuesTransparent (); |
|
|
|
loop.DrawRenderers (ref settings); |
|
|
|
settings.inputFilter.SetQueuesTransparent(); |
|
|
|
context.DrawRenderers(ref settings); |
|
|
|
loop.Submit (); |
|
|
|
context.Submit(); |
|
|
|
static void SetupLightShaderVariables (VisibleLight[] lights, RenderLoop loop) |
|
|
|
|
|
|
|
private static void SetupLightShaderVariables(VisibleLight[] lights, ScriptableRenderContext context) |
|
|
|
{ |
|
|
|
// We only support up to 8 visible lights here. More complex approaches would
|
|
|
|
// be doing some sort of per-object light setups, but here we go for simplest possible
|
|
|
|
|
|
|
// to the viewer, so that "most important" lights in the scene are picked, and not the 8
|
|
|
|
// that happened to be first.
|
|
|
|
int lightCount = Mathf.Min (lights.Length, kMaxLights); |
|
|
|
int lightCount = Mathf.Min(lights.Length, kMaxLights); |
|
|
|
|
|
|
|
// Prepare light data
|
|
|
|
Vector4[] lightColors = new Vector4[kMaxLights]; |
|
|
|
|
|
|
if (light.lightType == LightType.Directional) |
|
|
|
{ |
|
|
|
// light position for directional lights is: (-direction, 0)
|
|
|
|
var dir = light.localToWorld.GetColumn (2); |
|
|
|
lightPositions[i] = new Vector4 (-dir.x, -dir.y, -dir.z, 0); |
|
|
|
var dir = light.localToWorld.GetColumn(2); |
|
|
|
lightPositions[i] = new Vector4(-dir.x, -dir.y, -dir.z, 0); |
|
|
|
var pos = light.localToWorld.GetColumn (3); |
|
|
|
lightPositions[i] = new Vector4 (pos.x, pos.y, pos.z, 1); |
|
|
|
var pos = light.localToWorld.GetColumn(3); |
|
|
|
lightPositions[i] = new Vector4(pos.x, pos.y, pos.z, 1); |
|
|
|
} |
|
|
|
// attenuation set in a way where distance attenuation can be computed:
|
|
|
|
// float lengthSq = dot(toLight, toLight);
|
|
|
|
|
|
|
// spot direction & attenuation
|
|
|
|
if (light.lightType == LightType.Spot) |
|
|
|
{ |
|
|
|
var dir = light.localToWorld.GetColumn (2); |
|
|
|
lightSpotDirections[i] = new Vector4 (-dir.x, -dir.y, -dir.z, 0); |
|
|
|
var dir = light.localToWorld.GetColumn(2); |
|
|
|
lightSpotDirections[i] = new Vector4(-dir.x, -dir.y, -dir.z, 0); |
|
|
|
float cosTheta = Mathf.Cos (radAngle * 0.25f); |
|
|
|
float cosPhi = Mathf.Cos (radAngle * 0.5f); |
|
|
|
float cosTheta = Mathf.Cos(radAngle * 0.25f); |
|
|
|
float cosPhi = Mathf.Cos(radAngle * 0.5f); |
|
|
|
lightAtten[i] = new Vector4 (cosPhi, (cosDiff != 0.0f) ? 1.0f / cosDiff : 1.0f, quadAtten, rangeSq); |
|
|
|
lightAtten[i] = new Vector4(cosPhi, (cosDiff != 0.0f) ? 1.0f / cosDiff : 1.0f, quadAtten, rangeSq); |
|
|
|
lightSpotDirections[i] = new Vector4 (0, 0, 1, 0); |
|
|
|
lightAtten[i] = new Vector4 (-1, 1, quadAtten, rangeSq); |
|
|
|
lightSpotDirections[i] = new Vector4(0, 0, 1, 0); |
|
|
|
lightAtten[i] = new Vector4(-1, 1, quadAtten, rangeSq); |
|
|
|
} |
|
|
|
} |
|
|
|
GetShaderConstantsFromNormalizedSH (ref ambientSH, shConstants); |
|
|
|
GetShaderConstantsFromNormalizedSH(ref ambientSH, shConstants); |
|
|
|
cmd.SetGlobalVectorArray ("globalLightColor", lightColors); |
|
|
|
cmd.SetGlobalVectorArray ("globalLightPos", lightPositions); |
|
|
|
cmd.SetGlobalVectorArray ("globalLightSpotDir", lightSpotDirections); |
|
|
|
cmd.SetGlobalVectorArray ("globalLightAtten", lightAtten); |
|
|
|
cmd.SetGlobalVector ("globalLightCount", new Vector4 (lightCount, 0, 0, 0)); |
|
|
|
cmd.SetGlobalVectorArray ("globalSH", shConstants); |
|
|
|
loop.ExecuteCommandBuffer (cmd); |
|
|
|
cmd.Dispose (); |
|
|
|
cmd.SetGlobalVectorArray("globalLightColor", lightColors); |
|
|
|
cmd.SetGlobalVectorArray("globalLightPos", lightPositions); |
|
|
|
cmd.SetGlobalVectorArray("globalLightSpotDir", lightSpotDirections); |
|
|
|
cmd.SetGlobalVectorArray("globalLightAtten", lightAtten); |
|
|
|
cmd.SetGlobalVector("globalLightCount", new Vector4(lightCount, 0, 0, 0)); |
|
|
|
cmd.SetGlobalVectorArray("globalSH", shConstants); |
|
|
|
context.ExecuteCommandBuffer(cmd); |
|
|
|
cmd.Dispose(); |
|
|
|
static void GetShaderConstantsFromNormalizedSH (ref SphericalHarmonicsL2 ambientProbe, Vector4[] outCoefficients) |
|
|
|
|
|
|
|
private static void GetShaderConstantsFromNormalizedSH(ref SphericalHarmonicsL2 ambientProbe, Vector4[] outCoefficients) |
|
|
|
{ |
|
|
|
for (int channelIdx = 0; channelIdx < 3; ++channelIdx) |
|
|
|
{ |
|
|
|