Exemplo n.º 1
0
 //GameObject lightQuad; <-- old code, unsure if this changed anything
 private void Start()
 {
     //In WebGL, too many iterations in the shader will cause it to fail, namely 1024 and more will crash the shader
             #if UNITY_WEBGL
     if (MapResolution == ShadowmapResolution.Res1024 || MapResolution == ShadowmapResolution.Res2048 || MapResolution == ShadowmapResolution.Res4096)
     {
         //Fallback to the next-highest quality
         MapResolution = ShadowmapResolution.Res512;
         Debug.LogWarning("WebGL does not support shadow quality of over 512");
     }
             #endif
 }
    //We use LateUpdate to make sure all transforms and everything has been properly applied, otherwise the shadows will drag
    void LateUpdate()
    {
        //In WebGL, too many iterations in the shader will cause it to fail, namely 1024 and more will crash the shader
                #if UNITY_WEBGL
        if (MapResolution == ShadowmapResolution.Res1024 || MapResolution == ShadowmapResolution.Res2048 || MapResolution == ShadowmapResolution.Res4096)
        {
            //Fallback to the next-highest quality
            MapResolution = ShadowmapResolution.Res512;
            Debug.LogWarning("WebGL does not support shadow quality of over 512");
        }
                #endif

        //Reset the switches for the shader
        Shader.DisableKeyword("QUALITY_CRAP");
        Shader.DisableKeyword("QUALITY_LOW");
        Shader.DisableKeyword("QUALITY_NORMAL");
        Shader.DisableKeyword("QUALITY_HIGH");
        Shader.DisableKeyword("QUALITY_HIGHER");
        Shader.DisableKeyword("QUALITY_BEST");

        //Set the current switch
        if (MapResolution == ShadowmapResolution.Res128)
        {
            Shader.EnableKeyword("QUALITY_CRAP");
        }
        else if (MapResolution == ShadowmapResolution.Res256)
        {
            Shader.EnableKeyword("QUALITY_LOW");
        }
        else if (MapResolution == ShadowmapResolution.Res512)
        {
            Shader.EnableKeyword("QUALITY_NORMAL");
        }
        else if (MapResolution == ShadowmapResolution.Res1024)
        {
            Shader.EnableKeyword("QUALITY_HIGH");
        }
        else if (MapResolution == ShadowmapResolution.Res2048)
        {
            Shader.EnableKeyword("QUALITY_HIGHER");
        }
        else if (MapResolution == ShadowmapResolution.Res4096)
        {
            Shader.EnableKeyword("QUALITY_BEST");
        }

        //Clear all lists and repopulate them. There's performance gains to be made here.
        //For example we could make each object's transform and scripts send a callback to update their listing
        //here, or something similar. This will be changed in the future
        occluders.Clear();
        lit.Clear();
        lights.Clear();
        foreach (LightSettings2D obj in (LightSettings2D[])GameObject.FindObjectsOfType <LightSettings2D>())
        {
            if (obj.CastShadows)
            {
                occluders.Add(obj);
            }
            if (obj.RecieveShadows)
            {
                lit.Add(obj);
            }
        }
        foreach (LightSource light in GameObject.FindObjectsOfType <LightSource>())
        {
            lights.Add(light);
        }

        buffer.Clear();                                                                                               //Clear the buffer
        buffer.GetTemporaryRT(Shader.PropertyToID("Lightmap_RT"), Screen.width, Screen.height, 0, textureFilterMode); //Set the first shader to be used
        buffer.SetRenderTarget(lightmap);                                                                             //Set the rendertarget to our lightmap texture
        buffer.ClearRenderTarget(false, true, shadowColor);                                                           //Clear the lightmap with the shadow color
        foreach (LightSource light in lights)                                                                         //Loop through each light and render out their small lightmap
        {
            if (!light.on)
            {
                continue;                 //Skip this light if it's not on, duh
            }
            //Set up the occluders map
            //NOTE: instead of using big values in the enum, we simply bit shift our 2 to get the resolution we want (basically raising 2 by the value set in the enum)
            buffer.GetTemporaryRT(Shader.PropertyToID("Occluders_RT"), 2 << (int)MapResolution, 2 << (int)MapResolution, 0, textureFilterMode);
            buffer.SetRenderTarget(occlusionMap);
            buffer.ClearRenderTarget(false, true, Color.clear);

            //Render occluders to occlusion map
            light.RecalculateMatrices();
            buffer.SetGlobalFloat(Shader.PropertyToID("_Alpha"), alphaThreshold);
            buffer.SetGlobalMatrix(Shader.PropertyToID("LIGHT_MVP"), light.mvp);
            buffer.SetGlobalMatrix(Shader.PropertyToID("LIGHT_PROJ"), GL.GetGPUProjectionMatrix(light.orthoProj, true));
            foreach (LightSettings2D occluder in occluders)
            {
                //If it's a spriterenderer, get the color assigned in the spriterenderer (alpha value is important here)
                //otherwise use the material color (again, alpha is what we are pulling this for)
                Renderer r = occluder.GetComponent <Renderer>();
                if (r as SpriteRenderer != null)
                {
                    buffer.SetGlobalColor(Shader.PropertyToID("_SpriteColor"), (r as SpriteRenderer).color);
                }
                else
                {
                    buffer.SetGlobalColor(Shader.PropertyToID("_SpriteColor"), r.material.color);
                }
                //Render to occlusion map
                buffer.DrawRenderer(r, occlusion);
            }

            //Render lookup map
            buffer.GetTemporaryRT(Shader.PropertyToID("Lookup_RT"), 2 << (int)MapResolution, 1, 0, textureFilterMode);
            buffer.SetGlobalVector(Shader.PropertyToID("_Resolution"), new Vector4(2 << (int)MapResolution, 2 << (int)MapResolution));
            buffer.SetGlobalFloat(Shader.PropertyToID("_SampleRange"), light.angle / 360f);
            buffer.SetGlobalTexture(Shader.PropertyToID("_OccTex"), occlusionMap);
            buffer.Blit(occlusionMap, lookupMap, lookupMat, 0);             //Blitting causes the occlusion map to be set as the texture input in the shader, neat
            buffer.ReleaseTemporaryRT(Shader.PropertyToID("Occluders_RT"));

            //Render light area
            buffer.GetTemporaryRT(Shader.PropertyToID("LightArea_RT"), 2 << (int)MapResolution, 2 << (int)MapResolution, 0, textureFilterMode);
            buffer.SetGlobalFloat(Shader.PropertyToID("_Intensity"), light.intensity);
            buffer.SetGlobalFloat(Shader.PropertyToID("_Blurring"), light.blurAmount);
            buffer.Blit(lookupMap, lightAreaMap, lightMat);
            buffer.ReleaseTemporaryRT(Shader.PropertyToID("Lookup_RT"));

            //Render into composite lightmap
            buffer.SetRenderTarget(lightmap);
            buffer.SetGlobalTexture(Shader.PropertyToID("LightArea_RT"), lightAreaMap);
            buffer.SetGlobalVector(Shader.PropertyToID("LightColor"), light.lightColor);
            buffer.DrawMesh(lightMesh, light.lightMvp, lightAccumulation);
            buffer.ReleaseTemporaryRT(Shader.PropertyToID("LightArea_RT"));
        }
        buffer.SetGlobalTexture(Shader.PropertyToID("Lightmap_RT"), lightmap);         //Set the composite lightmap as a global texture for easy shader access
        buffer.SetGlobalFloat(Shader.PropertyToID("_BlendMode"), (int)blendMode);      //Also set the blendmode
    }