static void Main(string[] args) { //Convert skybox texture. { SoftwareImage <R32G32B32A32F> image = HdrImageLoader.Read(TestSceneResource("473-free-hdri-skies-com.hdr")); { var cubeImages = new SkyboxUniformCircleFilter <R32G32B32A32F>(image).Generate(32); SoftwareImage <R32G32B32A32F> .WriteSRDFileCube(TestSceneCompiled("sphere_cube_specular.srd"), cubeImages); } { var s1 = new HalfSize <R32G32B32A32F>(image).Generate(); s1 = new HalfSize <R32G32B32A32F>(s1).Generate(); s1 = new HalfSize <R32G32B32A32F>(s1).Generate(); s1 = new HalfSize <R32G32B32A32F>(s1).Generate(); s1 = new HalfSize <R32G32B32A32F>(s1).Generate(); image = s1; } image.WriteSRDFile(TestSceneCompiled("473-free-hdri-skies-com.srd")); { var cubeImages = new SkyboxLambertianDiffuseFilter <R32G32B32A32F>(image).Generate(16, 64); for (int i = 0; i < 6; ++i) { cubeImages[i] = new HalfSize <R32G32B32A32F>(cubeImages[i]).Generate(); cubeImages[i] = new HalfSize <R32G32B32A32F>(cubeImages[i]).Generate(); } SoftwareImage <R32G32B32A32F> .WriteSRDFileCube(TestSceneCompiled("sphere_cube_diffuse.srd"), cubeImages); } } //Generate model. { var model = Sphere.Generate(); model.WriteSRD(TestSceneCompiled("sphere.vb"), TestSceneCompiled("sphere.ib")); } { var model = ObjModelLoader.Load(TestSceneResource("bunny.obj.dat")); SwapModelCoordinate.SwapXZ(model); model.WriteSRD(TestSceneCompiled("bunny.vb"), TestSceneCompiled("bunny.ib")); } }
static void Main(string[] args) { var normalMap = new SoftwareImage <R32G32B32A32F>(800, 600, new R32G32B32A32FTransformer()); normalMap.LoadRawDataFile(TestSceneCompiled("OutputNormal.raw")); var viewDirMap = new SoftwareImage <R32G32B32A32F>(800, 600, new R32G32B32A32FTransformer()); viewDirMap.LoadRawDataFile(TestSceneCompiled("OutputViewDir.raw")); SoftwareImage <R32G32B32A32F> skybox = HdrImageLoader.Read(TestSceneResource("473-free-hdri-skies-com.hdr")); SoftwareImage <R32G32B32A32F> skyboxSpecular = skybox; { skyboxSpecular = new HalfSize <R32G32B32A32F>(skyboxSpecular).Generate(); skyboxSpecular = new HalfSize <R32G32B32A32F>(skyboxSpecular).Generate(); skyboxSpecular = new HalfSize <R32G32B32A32F>(skyboxSpecular).Generate(); skyboxSpecular = new HalfSize <R32G32B32A32F>(skyboxSpecular).Generate(); skyboxSpecular = new HalfSize <R32G32B32A32F>(skyboxSpecular).Generate(); } SoftwareImage <R32G32B32A32F> skyboxDiffuse = skybox; { skyboxDiffuse = new HalfSize <R32G32B32A32F>(skyboxDiffuse).Generate(); skyboxDiffuse = new HalfSize <R32G32B32A32F>(skyboxDiffuse).Generate(); skyboxDiffuse = new HalfSize <R32G32B32A32F>(skyboxDiffuse).Generate(); skyboxDiffuse = new HalfSize <R32G32B32A32F>(skyboxDiffuse).Generate(); skyboxDiffuse = new HalfSize <R32G32B32A32F>(skyboxDiffuse).Generate(); skyboxDiffuse = new HalfSize <R32G32B32A32F>(skyboxDiffuse).Generate(); skyboxDiffuse = new HalfSize <R32G32B32A32F>(skyboxDiffuse).Generate(); } var p = skybox.PixelTransformer; //System.Drawing.Bitmap does not support concurrent SetPixel. Use our own instead. var bitmap = new SoftwareImage <R8G8B8A8>(800, 600, new R8G8B8A8Transformer()); Parallel.For(0, 600, (int y) => { var rand = _rand.Value; for (int x = 0; x < 800; ++x) { var normal = normalMap.GetPixel(x, y); if (normal.R == 0 && normal.G == 0 && normal.B == 0) { continue; } var viewDir = viewDirMap.GetPixel(x, y); var n = new Vector3(normal.R, normal.G, normal.B); var e = Vector3.Normalize(-new Vector3(viewDir.R, viewDir.G, viewDir.B)); var l = Vector3.Normalize(2 * Vector3.Dot(n, e) * n - e); R32G32B32A32F color = default; //Specular { //color = p.Add(color, SkyboxHelper.SampleEquirectangularMap(skyboxSpecular, l)); const int SpecularSampleCount = 40; var sampler = new SphereDirectionalSampler(rand, l, (float)Math.PI / 2, SpecularSampleCount); R32G32B32A32F total = default; for (int sample = 0; sample < sampler.SampleCount; ++sample) { var sampleDir = sampler.Sample(sample); if (Vector3.Dot(sampleDir, n) < 0) { continue; } var cc = SkyboxHelper.SampleEquirectangularMap(skyboxSpecular, sampleDir); total = p.Add(total, p.Scale(cc, Vector3.Dot(n, sampleDir) * (float)BRDF(n, sampleDir, e))); } color = p.Add(color, p.Scale(total, 1f / sampler.SampleCount * 5)); } //Diffuse { const int DiffuseSampleCount = 10; var sampler = new SphereDirectionalSampler(rand, n, (float)Math.PI / 2, DiffuseSampleCount); R32G32B32A32F total = default; for (int sample = 0; sample < sampler.SampleCount; ++sample) { var sampleDir = sampler.Sample(sample); var cc = SkyboxHelper.SampleEquirectangularMap(skyboxDiffuse, sampleDir); total = p.Add(total, p.Scale(cc, Vector3.Dot(n, sampleDir) / (float)Math.PI)); } color = p.Add(color, p.Scale(total, 1f / sampler.SampleCount * 0)); } var rgb = p.ToColor(color); bitmap.GetPixel(x, y) = new R8G8B8A8 { R = rgb.R, G = rgb.G, B = rgb.B, A = 255, }; } //} }); bitmap.ToBitmap().Save(TestSceneCompiled("Offline.png")); }