You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
5.1 KiB
JavaScript
153 lines
5.1 KiB
JavaScript
2 months ago
|
|
||
|
|
||
|
@script ExecuteInEditMode
|
||
|
@script RequireComponent (Camera)
|
||
|
@script AddComponentMenu ("Image Effects/Sun Shafts")
|
||
|
|
||
|
enum SunShaftsResolution {
|
||
|
Low = 0,
|
||
|
Normal = 1,
|
||
|
High = 2,
|
||
|
}
|
||
|
|
||
|
enum ShaftsScreenBlendMode {
|
||
|
Screen = 0,
|
||
|
Add = 1,
|
||
|
}
|
||
|
|
||
|
class SunShafts extends PostEffectsBase
|
||
|
{
|
||
|
public var resolution : SunShaftsResolution = SunShaftsResolution.Normal;
|
||
|
public var screenBlendMode : ShaftsScreenBlendMode = ShaftsScreenBlendMode.Screen;
|
||
|
|
||
|
public var sunTransform : Transform;
|
||
|
public var radialBlurIterations : int = 2;
|
||
|
public var sunColor : Color = Color.white;
|
||
|
public var sunShaftBlurRadius : float = 2.5f;
|
||
|
public var sunShaftIntensity : float = 1.15;
|
||
|
public var useSkyBoxAlpha : float = 0.75f;
|
||
|
|
||
|
public var maxRadius : float = 0.75f;
|
||
|
|
||
|
public var useDepthTexture : boolean = true;
|
||
|
|
||
|
public var sunShaftsShader : Shader;
|
||
|
private var sunShaftsMaterial : Material;
|
||
|
|
||
|
public var simpleClearShader : Shader;
|
||
|
private var simpleClearMaterial : Material;
|
||
|
|
||
|
function OnDisable()
|
||
|
{
|
||
|
if (sunShaftsMaterial)
|
||
|
DestroyImmediate(sunShaftsMaterial);
|
||
|
if (simpleClearMaterial)
|
||
|
DestroyImmediate(simpleClearMaterial);
|
||
|
}
|
||
|
|
||
|
function CheckResources () : boolean {
|
||
|
CheckSupport (useDepthTexture);
|
||
|
|
||
|
sunShaftsMaterial = CheckShaderAndCreateMaterial (sunShaftsShader, sunShaftsMaterial);
|
||
|
simpleClearMaterial = CheckShaderAndCreateMaterial (simpleClearShader, simpleClearMaterial);
|
||
|
|
||
|
if(!isSupported)
|
||
|
ReportAutoDisable ();
|
||
|
return isSupported;
|
||
|
}
|
||
|
|
||
|
function OnRenderImage (source : RenderTexture, destination : RenderTexture) {
|
||
|
if(CheckResources()==false) {
|
||
|
Graphics.Blit (source, destination);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// we actually need to check this every frame
|
||
|
if(useDepthTexture)
|
||
|
camera.depthTextureMode |= DepthTextureMode.Depth;
|
||
|
|
||
|
var divider : float = 4.0;
|
||
|
if (resolution == SunShaftsResolution.Normal)
|
||
|
divider = 2.0;
|
||
|
else if (resolution == SunShaftsResolution.High)
|
||
|
divider = 1.0;
|
||
|
|
||
|
var v : Vector3 = Vector3.one * 0.5;
|
||
|
if (sunTransform)
|
||
|
v = camera.WorldToViewportPoint (sunTransform.position);
|
||
|
else
|
||
|
v = Vector3(0.5, 0.5, 0.0);
|
||
|
|
||
|
var secondQuarterRezColor : RenderTexture = RenderTexture.GetTemporary (source.width / divider, source.height / divider, 0);
|
||
|
var lrDepthBuffer : RenderTexture = RenderTexture.GetTemporary (source.width / divider, source.height / divider, 0);
|
||
|
|
||
|
// mask out everything except the skybox
|
||
|
// we have 2 methods, one of which requires depth buffer support, the other one is just comparing images
|
||
|
|
||
|
sunShaftsMaterial.SetVector ("_BlurRadius4", Vector4 (1.0, 1.0, 0.0, 0.0) * sunShaftBlurRadius );
|
||
|
sunShaftsMaterial.SetVector ("_SunPosition", Vector4 (v.x, v.y, v.z, maxRadius));
|
||
|
sunShaftsMaterial.SetFloat ("_NoSkyBoxMask", 1.0f - useSkyBoxAlpha);
|
||
|
|
||
|
if (!useDepthTexture) {
|
||
|
var tmpBuffer : RenderTexture = RenderTexture.GetTemporary (source.width, source.height, 0);
|
||
|
RenderTexture.active = tmpBuffer;
|
||
|
GL.ClearWithSkybox (false, camera);
|
||
|
|
||
|
sunShaftsMaterial.SetTexture ("_Skybox", tmpBuffer);
|
||
|
Graphics.Blit (source, lrDepthBuffer, sunShaftsMaterial, 3);
|
||
|
RenderTexture.ReleaseTemporary (tmpBuffer);
|
||
|
}
|
||
|
else {
|
||
|
Graphics.Blit (source, lrDepthBuffer, sunShaftsMaterial, 2);
|
||
|
}
|
||
|
|
||
|
// paint a small black small border to get rid of clamping problems
|
||
|
DrawBorder (lrDepthBuffer, simpleClearMaterial);
|
||
|
|
||
|
// radial blur:
|
||
|
|
||
|
radialBlurIterations = ClampBlurIterationsToSomethingThatMakesSense (radialBlurIterations);
|
||
|
|
||
|
var ofs : float = sunShaftBlurRadius * (1.0f / 768.0f);
|
||
|
|
||
|
sunShaftsMaterial.SetVector ("_BlurRadius4", Vector4 (ofs, ofs, 0.0f, 0.0f));
|
||
|
sunShaftsMaterial.SetVector ("_SunPosition", Vector4 (v.x, v.y, v.z, maxRadius));
|
||
|
|
||
|
for (var it2 : int = 0; it2 < radialBlurIterations; it2++ ) {
|
||
|
// each iteration takes 2 * 6 samples
|
||
|
// we update _BlurRadius each time to cheaply get a very smooth look
|
||
|
|
||
|
Graphics.Blit (lrDepthBuffer, secondQuarterRezColor, sunShaftsMaterial, 1);
|
||
|
ofs = sunShaftBlurRadius * (((it2 * 2.0f + 1.0f) * 6.0f)) / 768.0f;
|
||
|
sunShaftsMaterial.SetVector ("_BlurRadius4", Vector4 (ofs, ofs, 0.0f, 0.0f) );
|
||
|
|
||
|
Graphics.Blit (secondQuarterRezColor, lrDepthBuffer, sunShaftsMaterial, 1);
|
||
|
ofs = sunShaftBlurRadius * (((it2 * 2.0f + 2.0f) * 6.0f)) / 768.0f;
|
||
|
sunShaftsMaterial.SetVector ("_BlurRadius4", Vector4 (ofs, ofs, 0.0f, 0.0f) );
|
||
|
}
|
||
|
|
||
|
// put together:
|
||
|
|
||
|
if (v.z >= 0.0)
|
||
|
sunShaftsMaterial.SetVector ("_SunColor", Vector4 (sunColor.r, sunColor.g, sunColor.b, sunColor.a) * sunShaftIntensity);
|
||
|
else
|
||
|
sunShaftsMaterial.SetVector ("_SunColor", Vector4.zero); // no backprojection !
|
||
|
sunShaftsMaterial.SetTexture ("_ColorBuffer", lrDepthBuffer);
|
||
|
Graphics.Blit (source, destination, sunShaftsMaterial, (screenBlendMode == ShaftsScreenBlendMode.Screen) ? 0 : 4);
|
||
|
|
||
|
RenderTexture.ReleaseTemporary (lrDepthBuffer);
|
||
|
RenderTexture.ReleaseTemporary (secondQuarterRezColor);
|
||
|
}
|
||
|
|
||
|
// helper functions
|
||
|
|
||
|
private function ClampBlurIterationsToSomethingThatMakesSense (its : int) : int {
|
||
|
if (its < 1)
|
||
|
return 1;
|
||
|
else if (its > 4)
|
||
|
return 4;
|
||
|
else
|
||
|
return its;
|
||
|
}
|
||
|
|
||
|
}
|