void Start() { for (int i = 0; i < 128; ++i) { for (int j = 0; j < 128; ++j) { uint scrambleU = 5569; uint scrambleV = 95597; // Vector2 randomSample = new Vector2(Random.value, Random.value); // Vector2 randomSample = new Vector2(i / 128.0f, j / 128.0f); Vector2 randomSample = RandomSamplers.Utils.Sample02((uint)(2211 + i + j * 128), scrambleU, scrambleV); DistributionSample halfwaySample = CosineDistribution.Sample(randomSample); //DistributionSample halfwaySample = PowerCosineDistribution.Sample(randomSample, 0); GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.position = halfwaySample.Direction * 10.0f; sphere.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f); } } for (int i = 0; i < 128; ++i) { for (int j = 0; j < 128; ++j) { uint scrambleU = 5569; uint scrambleV = 95597; Vector2 randomSample = RandomSamplers.Utils.Sample02((uint)(2211 + 128 * 128 + i + j * 128), scrambleU, scrambleV); DistributionSample halfwaySample = CosineDistribution.Sample(randomSample); //DistributionSample halfwaySample = PowerCosineDistribution.Sample(randomSample, 0); GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.position = new Vector3(halfwaySample.Direction.x * 10.0f, halfwaySample.Direction.y * -10.0f, halfwaySample.Direction.z * 10.0f); sphere.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f); } } }
public static void ConvoluteLatLong(Texture2D inputMap) { Texture2D convoluted = new Texture2D(inputMap.width, inputMap.height, TextureFormat.RGB24, true); convoluted.filterMode = FilterMode.Trilinear; convoluted.name = inputMap.name + "_Convoluted"; convoluted.SetPixels(inputMap.GetPixels()); convoluted.Apply(false); Color[] srcPixels = convoluted.GetPixels(); int srcWidth = convoluted.width; int srcHeight = convoluted.height; int mipmapCount = convoluted.mipmapCount; // Calc total pixels, used by the progress bar and not counting the // zero'th layer as it is processed nearly instantatious. int totalPixelCount = 0; for (int m = 1; m < mipmapCount; ++m) { int mipWidth = convoluted.width >> m; if (mipWidth == 0) { mipWidth = 1; } int mipHeight = convoluted.height >> m; if (mipHeight == 0) { mipHeight = 1; } totalPixelCount += mipHeight * mipWidth; } Vector2[] randomSamples = new Vector2[SAMPLES]; uint scrambleU = 5569; uint scrambleV = 95597; for (uint s = 0; s < SAMPLES; ++s) { randomSamples[s] = RandomSamplers.Utils.Sample02(2211 + s, scrambleU, scrambleV); } System.DateTime start = System.DateTime.Now; // Convolute each miplevel seperately int pixelsProcessed = 0; for (int mipLevel = mipmapCount - 1; mipLevel > 0; --mipLevel) { int mipWidth = convoluted.width >> mipLevel; if (mipWidth == 0) { mipWidth = 1; } int mipHeight = convoluted.height >> mipLevel; if (mipHeight == 0) { mipHeight = 1; } EditorUtility.DisplayProgressBar("Convoluting lat long skybox", "Processing " + inputMap.name, pixelsProcessed / (float)totalPixelCount); float exponent = ExponentFromMipLevel(mipLevel, mipmapCount - 2); Debug.Log("shininess " + exponent + " at mip level " + mipLevel + " of " + mipmapCount); // Loop over all pixels Color[] pixels = new Color[mipWidth * mipHeight]; Threading.Parallel.For(mipWidth, u => { float phi = (((u + 0.5f) / (float)mipWidth)) * 2.0f * Mathf.PI; for (int v = 0; v < mipHeight; ++v) { float theta = (1.0f - (v + 0.5f) / (float)mipHeight) * Mathf.PI; // Compute direction Vector3 normal = Utils.Cubemap.SphericalToDirection(theta, phi).normalized; Vector3 tangent, bitangent; CreateTangents(normal, out tangent, out bitangent); // Create samples and sample Color summedColor = new Color(0.0f, 0.0f, 0.0f, 0.0f); float totalWeight = 0.0f; for (int s = 0; s < SAMPLES; ++s) { DistributionSample halfwaySample = PowerCosineDistribution.Sample(randomSamples[s], exponent); if (halfwaySample.PDF > 0.0f) { halfwaySample.Direction = tangent * halfwaySample.Direction.x + normal * halfwaySample.Direction.y + bitangent * halfwaySample.Direction.z; Vector2 sampleUV = Utils.Cubemap.DirectionToSphericalUV(halfwaySample.Direction); // TODO Perform own repeat-clamp sampling ? int x = (int)(sampleUV.x * (srcWidth - 1)); int y = (int)(sampleUV.y * (srcHeight - 1)); Color sample = srcPixels[x + y * srcWidth]; float lightScale = Vector3.Dot(halfwaySample.Direction, normal); summedColor += sample * lightScale; totalWeight += lightScale; } } int index = u + v * mipWidth; pixels[index] = summedColor / totalWeight; } } ); convoluted.SetPixels(pixels, mipLevel); pixelsProcessed += mipWidth * mipHeight; } EditorUtility.DisplayProgressBar("Convoluting lat long skybox", "Saving " + inputMap.name, 0.99f); convoluted.Apply(false, true); string sourcePath = AssetDatabase.GetAssetPath(inputMap); string saveFolder = System.IO.Path.GetDirectoryName(sourcePath); string destPath = saveFolder + "/" + convoluted.name + ".asset"; AssetDatabase.CreateAsset(convoluted, destPath); Texture2D.DestroyImmediate(convoluted); EditorUtility.ClearProgressBar(); System.DateTime stop = System.DateTime.Now; Debug.Log("Conveluted " + sourcePath + " in " + (stop - start).TotalSeconds + "seconds."); }