示例#1
0
        private void SetupAreaLight(Light light)
        {
            BakeryLightMesh bakeryLightMesh = light.GetComponent <BakeryLightMesh>();

            if (bakeryLightMesh == null)
            {
                bakeryLightMesh = light.gameObject.AddComponent <BakeryLightMesh>();
            }
            if (PlayerSettings.colorSpace != ColorSpace.Linear)
            {
                bakeryLightMesh.color     = light.color;
                bakeryLightMesh.intensity = light.intensity;
            }
            else if (!GraphicsSettings.lightsUseLinearIntensity)
            {
                float lightR, lightG, lightB, lightInt;
                GetLinearLightParameters(light, out lightR, out lightG, out lightB, out lightInt);
                bakeryLightMesh.color     = new Color(lightR, lightG, lightB);
                bakeryLightMesh.intensity = lightInt;
            }
            else
            {
                bakeryLightMesh.color     = light.color;
                bakeryLightMesh.intensity = light.intensity;
            }
            bakeryLightMesh.samples           = meshSamples[1];
            bakeryLightMesh.samples2          = meshSamples[0];
            bakeryLightMesh.cutoff            = light.range * 1.5f;
            bakeryLightMesh.selfShadow        = false;
            bakeryLightMesh.bitmask           = 1;
            bakeryLightMesh.indirectIntensity = light.bounceIntensity;
        }
示例#2
0
    static public void BuildLight(BakeryLightMesh obj, int SAMPLES, string outName = "lights.bin")
    {
        if (!allowOverwrite && lightSaved.ContainsKey(outName))
        {
            return;
        }
        lightSaved[outName] = true;

        var folder = ftBuildGraphics.scenePath;//Directory.GetParent(Application.dataPath).FullName + "/frender";

        if (!Directory.Exists(folder))
        {
            Directory.CreateDirectory(folder);
        }
        var f = new BinaryWriter(File.Open(folder + "/" + outName, FileMode.Create));

        f.Write(1);
        var mesh    = obj.GetComponent <MeshFilter>().sharedMesh;
        var tform   = obj.transform;
        var verts   = mesh.vertices;
        var indices = mesh.triangles;
        int tris    = indices.Length / 3;

        float[] area = new float[tris];
#if (OPTIMIZEDAREA || OPTIMIZEDAREA2)
#else
        float minArea = float.MaxValue;
        float maxArea = -float.MaxValue;
#endif
        float totalWorldArea = 0;

        Vector2[] uv            = null;
        int       downsampleRes = 0;
        float[]   pixels        = null;
        string    texName       = "";
        if (obj.texture != null)
        {
            uv = mesh.uv;
            var tex = obj.texture;

            // Save original texture to RGBA32F DDS
            int existingTexHash;
            if (!tex2hash.TryGetValue(tex, out existingTexHash))
            {
                existingTexHash = -1;
            }
            if (existingTexHash < 0)
            {
                int texHash = tex.GetHashCode();
                tex2hash[tex]   = texHash;
                existingTexHash = texHash;
            }
            texName = "areatex_" + existingTexHash;

            ftBuildGraphics.InitShaders();
            ftBuildGraphics.SaveCookie(tex.GetNativeTexturePtr(),
                                       folder + "/" + texName + ".dds"
                                       );
            GL.IssuePluginEvent(4);

            // Get downsampled (via mips) texture
            downsampleRes = (int)Mathf.Sqrt(SAMPLES);
            if (downsampleRes == 0)
            {
                downsampleRes = 1;
            }
            var downsampleRT  = new RenderTexture(downsampleRes, downsampleRes, 0, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
            var downsampleTex = new Texture2D(downsampleRes, downsampleRes, TextureFormat.RGBAFloat, false, true);
            Graphics.Blit(tex, downsampleRT);
            Graphics.SetRenderTarget(downsampleRT);
            downsampleTex.ReadPixels(new Rect(0, 0, downsampleRes, downsampleRes), 0, 0, false);
            downsampleTex.Apply();
            var bytes = downsampleTex.GetRawTextureData();
            pixels = new float[bytes.Length / 4];
            System.Buffer.BlockCopy(bytes, 0, pixels, 0, bytes.Length);
        }

        for (int j = 0; j < tris; j++)
        {
            var v1 = verts[indices[j * 3]];
            var v2 = verts[indices[j * 3 + 1]];
            var v3 = verts[indices[j * 3 + 2]];

            v1 = tform.TransformPoint(v1);
            v2 = tform.TransformPoint(v2);
            v3 = tform.TransformPoint(v3);

#if (OPTIMIZEDAREA || OPTIMIZEDAREA2)
            area[j] = Vector3.Cross(v2 - v1, v3 - v1).magnitude;
            if (area[j] > 0)
            {
                totalWorldArea += area[j];
            }
#else
            area[j] = Vector3.Cross(v2 - v1, v3 - v1).magnitude;
            if (area[j] > 0)
            {
                totalWorldArea += area[j];
            }
            if (area[j] > 0)
            {
                minArea = Mathf.Min(minArea, area[j]);
                maxArea = Mathf.Max(maxArea, area[j]);
            }
#endif
        }

#if OPTIMIZEDAREA2
        // New 2
        var   randomTriIndices = new int[SAMPLES];
        float invTotalArea     = 1.0f / (totalWorldArea * 0.5f);
        float sumWeights       = 0.0f;
        for (int j = 0; j < tris; j++)
        {
            area[j]    *= invTotalArea * 0.5f;
            sumWeights += area[j];
        }

        float sampleWidth    = sumWeights / SAMPLES;
        int   outputSampleIx = -1;
        float weightSoFar    = -Random.value * sampleWidth;
        for (int i = 0; i < SAMPLES; i++)
        {
            float sampleDist = i * sampleWidth;
            while (sampleDist >= weightSoFar && outputSampleIx + 1 < tris)
            {
                weightSoFar += area[++outputSampleIx];
            }
            randomTriIndices[i] = outputSampleIx;
        }
#elif OPTIMIZEDAREA
        // New

        // Collect indices to triangles
        var   triIndices   = new int[tris];
        float invTotalArea = 1.0f / (totalWorldArea * 0.5f);
        for (int j = 0; j < tris; j++)
        {
            area[j]      *= invTotalArea * 0.5f;
            triIndices[j] = j;
        }

        // Sort triangle indices by area (probability)
        // Smaller -> Larger
        System.Array.Sort(triIndices, delegate(int a, int b)
        {
            return(area[a].CompareTo(area[b]));
        });

        // Put triangle indices into a BSP tree based on area
        int start = 0;
        int end   = triIndices.Length - 1;
        //var bspLayers = new List<int[]>(); // tri index array per depth level
        var bspRoot = BuildProbabilityBSP(triIndices, area, start, end, 0, 0.0f, 1.0f);
#else
        // Legacy
        if (maxArea / minArea > 65535)
        {
            minArea = maxArea / 65535;
        }
        float invMinArea = 1.0f / minArea;
        for (int j = 0; j < tris; j++)
        {
            area[j] *= invMinArea;
            area[j]  = Mathf.Round(area[j]);
        }

        int skipped        = 0;
        var uniformTriList = new List <int>();
        for (int j = 0; j < tris; j++)
        {
            var tarea = area[j];
            if (tarea > 0 && tarea < 65536)
            {
                for (int k = 0; k < tarea; k++)
                {
                    uniformTriList.Add(j);
                }
            }
            else
            {
                skipped++;
            }
        }

        if (skipped > 0)
        {
            Debug.LogError("Skipped " + skipped + " invalid triangles out of " + tris + " on LightMesh " + obj.name + " (area is too big?)");
        }
#endif


        f.Write(obj.samples2);
        f.Write(SAMPLES);
        Vector3 trinormal;
        for (int sample = 0; sample < SAMPLES; sample++)
        {
#if OPTIMIZEDAREA2
            int tri = randomTriIndices[sample];
#elif OPTIMIZEDAREA
            int tri = GetRandomTriFromBSP(bspRoot, Random.value);
            //Debug.LogError(tri);
#else
            int rndTri = Random.Range(0, uniformTriList.Count);
            int tri    = uniformTriList.Count > 0 ? uniformTriList[rndTri] : 0;
#endif

            var rndA = Random.value;
            var rndB = Random.value;
            var rndC = Random.value;

            var A     = verts[indices[tri * 3]];
            var B     = verts[indices[tri * 3 + 1]];
            var C     = verts[indices[tri * 3 + 2]];
            var point = (1.0f - Mathf.Sqrt(rndA)) * A + (Mathf.Sqrt(rndA) * (1.0f - rndB)) * B + (Mathf.Sqrt(rndA) * rndB) * C;

            point = tform.TransformPoint(point);

            trinormal = Vector3.Cross(A - B, B - C).normalized;
            trinormal = tform.TransformDirection(trinormal);

            point += trinormal * 0.001f;

            f.Write(point.x);
            f.Write(point.y);
            f.Write(point.z);

            f.Write(trinormal.x);
            f.Write(trinormal.y);
            f.Write(trinormal.z);

            if (obj.texture != null)
            {
                var tA         = uv[indices[tri * 3]];
                var tB         = uv[indices[tri * 3 + 1]];
                var tC         = uv[indices[tri * 3 + 2]];
                var tpoint     = (1.0f - Mathf.Sqrt(rndA)) * tA + (Mathf.Sqrt(rndA) * (1.0f - rndB)) * tB + (Mathf.Sqrt(rndA) * rndB) * tC;
                int tx         = (int)(tpoint.x * (downsampleRes - 1));
                int ty         = (int)(tpoint.y * (downsampleRes - 1));
                int pixelIndex = ty * downsampleRes + tx;
                if (pixelIndex * 4 + 2 < pixels.Length)
                {
                    float cr = pixels[pixelIndex * 4];
                    float cg = pixels[pixelIndex * 4 + 1];
                    float cb = pixels[pixelIndex * 4 + 2];
                    f.Write(cr);
                    f.Write(cg);
                    f.Write(cb);
                }
                else
                {
                    f.Write(0.0f);
                    f.Write(0.0f);
                    f.Write(0.0f);
                }
            }

            //var g = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            //g.transform.position = point;
            //g.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f);
        }

        f.Write(obj.cutoff);
        f.Write(totalWorldArea * 0.5f);

        #if SRGBCONVERT
        f.Write(obj.color.linear.r * obj.intensity);
        f.Write(obj.color.linear.g * obj.intensity);
        f.Write(obj.color.linear.b * obj.intensity);
        #else
        f.Write(obj.color.r * obj.intensity);
        f.Write(obj.color.g * obj.intensity);
        f.Write(obj.color.b * obj.intensity);
        #endif

        f.Write(obj.lmid);

        if (obj.texture != null)
        {
            f.Write(texName + ".dds");
        }

        f.Close();
    }