topical media & game development

talk show tell print

lib-unity-demo-shader-Assets-Depth-of-Field-DepthOfFieldEffect.js / js



  #pragma strict
  
  @script ExecuteInEditMode
  @script AddComponentMenu("Image Effects/Depth Of Field")
  @script RequireComponent(Camera)
  
  var focalDistance = 5.0;
  var focalRange = 10.0;
  
  
Blur iterations - larger number means more blur.
var iterations = 1; var iterations2 = 2;
Blur spread for each iteration. Lower values
give better looking blur, but require more iterations to
get large blurs. Value is usually between 0.5 and 1.0.
var blurSpread = 0.6; var renderSceneShader : Shader; var compositeShader : Shader; // -------------------------------------------------------- // The blur iteration shader. // Basically it just takes 4 texture samples and averages them. // By applying it repeatedly and spreading out sample locations // we get a Gaussian blur approximation. private static var blurMatString = "Shader \"BlurConeTap\" { SubShader { Pass { " + "ZTest Always Cull Off ZWrite Off Fog { Mode Off } " + " SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant alpha} " + " SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant + previous} " + " SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant + previous} " + " SetTexture [__RenderTex] {constantColor (0,0,0,0.25) combine texture * constant + previous} " + "} } Fallback off }"; private var m_Material : Material; private function GetMaterial() : Material { if (m_Material == null) { m_Material = new Material( blurMatString ); m_Material.hideFlags = HideFlags.HideAndDontSave; m_Material.shader.hideFlags = HideFlags.HideAndDontSave; } return m_Material; } private var m_CompositeMaterial : Material; private function GetCompositeMaterial() : Material { if (m_CompositeMaterial == null) { m_CompositeMaterial = new Material( compositeShader ); m_CompositeMaterial.hideFlags = HideFlags.HideAndDontSave; } return m_CompositeMaterial; } private var renderTexture : RenderTexture; private var shaderCamera : GameObject; function OnDisable() { if( m_Material ) { DestroyImmediate( m_Material.shader ); DestroyImmediate( m_Material ); } DestroyImmediate (m_CompositeMaterial); DestroyImmediate (shaderCamera); if (renderTexture != null) { RenderTexture.ReleaseTemporary (renderTexture); renderTexture = null; } } // -------------------------------------------------------- function Start() { // Disable if we don't support image effects if (!SystemInfo.supportsImageEffects) { enabled = false; return; } // Disable if the shader(s) can't run on the users graphics card if (!GetMaterial().shader.isSupported || !GetCompositeMaterial().shader.isSupported) { enabled = false; return; } if (!renderSceneShader || !renderSceneShader.isSupported) { enabled = false; return; } } // -------------------------------------------------------- function OnPreRender() { if (!enabled || !gameObject.active) return; if (renderTexture != null) { RenderTexture.ReleaseTemporary (renderTexture); renderTexture = null; } renderTexture = RenderTexture.GetTemporary (camera.pixelWidth, camera.pixelHeight, 16); if (!shaderCamera) { shaderCamera = new GameObject("ShaderCamera", Camera); shaderCamera.camera.enabled = false; shaderCamera.hideFlags = HideFlags.HideAndDontSave; } var cam = shaderCamera.camera; cam.CopyFrom (camera); cam.backgroundColor = Color(1,1,1,1); cam.clearFlags = CameraClearFlags.SolidColor; cam.targetTexture = renderTexture; cam.RenderWithShader (renderSceneShader, "RenderType"); } // -------------------------------------------------------- // Performs one blur iteration. private function FourTapCone (source : RenderTexture, dest : RenderTexture, iteration : int) : void { RenderTexture.active = dest; source.SetGlobalShaderProperty ("__RenderTex"); var offsetX = (0.5+iteration*blurSpread) / source.width; var offsetY = (0.5+iteration*blurSpread) / source.height; GL.PushMatrix (); GL.LoadOrtho (); var mat = GetMaterial(); for (var i = 0; i < mat.passCount; ++i) { mat.SetPass (i); Render4TapQuad( dest, offsetX, offsetY ); } GL.PopMatrix (); } // Downsamples the texture to a quarter resolution. private function DownSample4x (source : RenderTexture, dest : RenderTexture) : void { RenderTexture.active = dest; source.SetGlobalShaderProperty ("__RenderTex"); var offsetX = 1.0 / source.width; var offsetY = 1.0 / source.height; GL.PushMatrix (); GL.LoadOrtho (); var mat = GetMaterial(); for (var i = 0; i < mat.passCount; ++i) { mat.SetPass (i); Render4TapQuad( dest, offsetX, offsetY ); } GL.PopMatrix (); } // Called by the camera to apply the image effect function OnRenderImage (source : RenderTexture, destination : RenderTexture) : void { var buffer1 = RenderTexture.GetTemporary(source.width/4, source.height/4, 0); var buffer2 = RenderTexture.GetTemporary(source.width/4, source.height/4, 0); var interm = RenderTexture.GetTemporary(source.width/4, source.height/4, 0); // Copy source to the 4x4 smaller texture. DownSample4x (source, buffer1); // Blur the small texture repeatedly var oddEven = true; for(var i = 0; i < iterations + iterations2; i++) { if( oddEven ) FourTapCone (buffer1, buffer2, i); else FourTapCone (buffer2, buffer1, i); oddEven = !oddEven; if (i==iterations-1) ImageEffects.Blit(oddEven ? buffer1 : buffer2, interm); } var compositeMat = GetCompositeMaterial(); compositeMat.SetTexture ("_BlurTex1", interm); compositeMat.SetTexture ("_BlurTex2", oddEven ? buffer1 : buffer2); compositeMat.SetTexture ("_DepthTex", renderTexture); Shader.SetGlobalVector ("_FocalParams", Vector4(focalDistance, 1.0/focalDistance, focalRange, 1.0/focalRange)); ImageEffects.BlitWithMaterial(compositeMat, source, destination); RenderTexture.ReleaseTemporary(buffer1); RenderTexture.ReleaseTemporary(buffer2); RenderTexture.ReleaseTemporary(interm); if (renderTexture != null) { RenderTexture.ReleaseTemporary (renderTexture); renderTexture = null; } } private static function Render4TapQuad( dest : RenderTexture, offsetX : float, offsetY : float ) : void { GL.Begin( GL.QUADS ); // Direct3D needs interesting texel offsets! var off = Vector2.zero; if( dest != null ) off = dest.GetTexelOffset() * 0.75; Set4TexCoords( off.x, off.y, offsetX, offsetY ); GL.Vertex3( 0,0, 0.1 ); Set4TexCoords( 1.0 + off.x, off.y, offsetX, offsetY ); GL.Vertex3( 1,0, 0.1 ); Set4TexCoords( 1.0 + off.x, 1.0 + off.y, offsetX, offsetY ); GL.Vertex3( 1,1, 0.1 ); Set4TexCoords( off.x, 1.0 + off.y, offsetX, offsetY ); GL.Vertex3( 0,1, 0.1 ); GL.End(); } private static function Set4TexCoords( x : float, y : float, offsetX : float, offsetY : float ) : void { GL.MultiTexCoord2( 0, x - offsetX, y - offsetY ); GL.MultiTexCoord2( 1, x + offsetX, y - offsetY ); GL.MultiTexCoord2( 2, x + offsetX, y + offsetY ); GL.MultiTexCoord2( 3, x - offsetX, y + offsetY ); }


(C) Æliens 04/09/2009

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.