public void Generate(Component_Mesh mesh, string writeRealFileName) { this.mesh = mesh; Init(); //create scene var scene = CreateScene(false); if (mesh != null) { var objInSpace = scene.CreateComponent <Component_MeshInSpace>(); objInSpace.Mesh = mesh; } scene.Enabled = true; //generate an image { viewport.Update(true); //clear temp data viewport.RenderingContext.MultiRenderTarget_DestroyAll(); viewport.RenderingContext.DynamicTexture_DestroyAll(); texture.Result.GetRealObject(true).BlitTo(viewport.RenderingContext.CurrentViewNumber, textureRead.Result.GetRealObject(true), 0, 0); var demandedFrame = textureRead.Result.GetRealObject(true).Read(imageData, 0); while (RenderingSystem.CallBgfxFrame() < demandedFrame) { } } //write png if (!ImageUtility.Save(writeRealFileName, imageData, imageSizeRender, 1, imageFormat, 1, 0, out var error)) { throw new Exception(error); } DetachAndOrDestroyScene(); Shutdown(); }
static bool GenerateFile(string sourceRealFileName, bool generateIrradiance, int destSize, string destRealFileName, List <Vector3> outIrradianceValues, out string error) { var tempDirectory = GetTemporaryDirectory(); string arguments; if (generateIrradiance) { arguments = $"--format=hdr --size={destSize} --type=cubemap --ibl-irradiance=\"{tempDirectory}\" \"{sourceRealFileName}\""; } else { arguments = $"--format=hdr --size={destSize} --type=cubemap -x \"{tempDirectory}\" \"{sourceRealFileName}\""; } var process = new Process(); process.StartInfo.FileName = Path.Combine(VirtualFileSystem.Directories.EngineInternal, @"Tools\Filament\cmgen.exe"); process.StartInfo.Arguments = arguments; process.Start(); process.WaitForExit(); var exitCode = process.ExitCode; if (exitCode != 0) { error = $"cmgen.exe exit code = {exitCode}."; return(false); } var folder = Path.Combine(tempDirectory, Path.GetFileNameWithoutExtension(sourceRealFileName)); int size; bool need16bit = false; { var file = Path.Combine(folder, generateIrradiance ? "i_nx.hdr" : "m0_nx.hdr"); var bytes = File.ReadAllBytes(file); if (!ImageUtility.LoadFromBuffer(bytes, "hdr", out var data, out var size2, out _, out var format, out _, out _, out error)) { return(false); } size = size2.X; if (format != PixelFormat.Float32RGB) { error = "format != PixelFormat.Float32RGB"; return(false); } var image2D = new ImageUtility.Image2D(format, size2, data); for (int y = 0; y < image2D.Size.Y; y++) { for (int x = 0; x < image2D.Size.X; x++) { var v = image2D.GetPixel(new Vector2I(x, y)); if (v.X > 1.001f || v.Y >= 1.001f || v.Z >= 1.001f) { need16bit = true; goto end16bit; } } } end16bit :; } var surfaces = new List <DDSImage.Surface>(); for (int face = 0; face < 6; face++) { int counter = 0; int currentSize = size; while (currentSize > 0) { var postfixes = new string[] { "px", "nx", "py", "ny", "pz", "nz" }; string file; if (generateIrradiance) { file = Path.Combine(folder, $"i_{postfixes[ face ]}.hdr"); } else { file = Path.Combine(folder, $"m{counter}_{postfixes[ face ]}.hdr"); } var bytes = File.ReadAllBytes(file); if (!ImageUtility.LoadFromBuffer(bytes, "hdr", out var data, out var size2, out _, out var format, out _, out _, out error)) { return(false); } if (format != PixelFormat.Float32RGB) { error = "format != PixelFormat.Float32RGB"; return(false); } if (size2.X != currentSize) { error = "size2.X != currentSize"; return(false); } if (need16bit) { byte[] newData = new byte[currentSize * currentSize * 4 * 2]; unsafe { fixed(byte *pData = data) { float *pData2 = (float *)pData; fixed(byte *pNewData = newData) { Half *pNewData2 = (Half *)pNewData; for (int n = 0; n < currentSize * currentSize; n++) { pNewData2[n * 4 + 0] = new Half(pData2[n * 3 + 0]); pNewData2[n * 4 + 1] = new Half(pData2[n * 3 + 1]); pNewData2[n * 4 + 2] = new Half(pData2[n * 3 + 2]); pNewData2[n * 4 + 3] = new Half(1.0f); } } } } surfaces.Add(new DDSImage.Surface(new Vector2I(currentSize, currentSize), newData)); } else { byte[] newData = new byte[currentSize * currentSize * 4]; unsafe { fixed(byte *pData = data) { float *pData2 = (float *)pData; for (int n = 0; n < currentSize * currentSize; n++) { newData[n * 4 + 3] = 255; newData[n * 4 + 2] = (byte)(MathEx.Saturate(pData2[n * 3 + 0]) * 255.0); newData[n * 4 + 1] = (byte)(MathEx.Saturate(pData2[n * 3 + 1]) * 255.0); newData[n * 4 + 0] = (byte)(MathEx.Saturate(pData2[n * 3 + 2]) * 255.0); } } } surfaces.Add(new DDSImage.Surface(new Vector2I(currentSize, currentSize), newData)); } counter++; currentSize /= 2; if (generateIrradiance) { break; } } } var image = new DDSImage(need16bit ? DDSImage.FormatEnum.R16G16B16A16 : DDSImage.FormatEnum.X8R8G8B8, surfaces.ToArray(), true); if (!WriteToFile(destRealFileName, image, out error)) { return(false); } if (outIrradianceValues != null) { var shFile = Path.Combine(folder, "sh.txt"); var lines = File.ReadAllLines(shFile); foreach (var line in lines) { var index1 = line.IndexOf('('); var index2 = line.IndexOf(')'); if (index1 != -1 && index2 != -1) { var str = line.Substring(index1 + 1, index2 - index1 - 1).Trim(); var strs = str.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (strs.Length != 3) { error = "Unable to parse \"sh.txt\"."; return(false); } var x = double.Parse(strs[0].Trim()); var y = double.Parse(strs[1].Trim()); var z = double.Parse(strs[2].Trim()); outIrradianceValues.Add(new Vector3(x, y, z)); } } } DeleteDirectory(tempDirectory); error = ""; return(true); }
public void UpdateCaptureCubemap() { if (Mode.Value != ModeEnum.Capture) { return; } Component_Image texture = null; Component_Image textureRead = null; try { //create var resolution = Resolution.Value; var hdr = HDR.Value; var size = int.Parse(resolution.ToString().Replace("_", "")); //!!!!16 бит достаточно, тогда нужно поддержку для Image2D PixelFormat format = hdr ? PixelFormat.Float32RGBA : PixelFormat.A8R8G8B8; //PixelFormat format = hdr ? PixelFormat.Float16RGBA : PixelFormat.A8R8G8B8; texture = ComponentUtility.CreateComponent <Component_Image>(null, true, false); texture.CreateType = Component_Image.TypeEnum._2D; texture.CreateSize = new Vector2I(size, size); texture.CreateMipmaps = false; texture.CreateFormat = format; texture.CreateUsage = Component_Image.Usages.RenderTarget; texture.CreateFSAA = 0; texture.Enabled = true; var renderTexture = texture.Result.GetRenderTarget(0, 0); //!!!! var viewport = renderTexture.AddViewport(true, false); //var viewport = renderTexture.AddViewport( false, false ); viewport.Mode = Viewport.ModeEnum.ReflectionProbeCubemap; viewport.AttachedScene = ParentScene; textureRead = ComponentUtility.CreateComponent <Component_Image>(null, true, false); textureRead.CreateType = Component_Image.TypeEnum._2D; textureRead.CreateSize = new Vector2I(size, size); textureRead.CreateMipmaps = false; textureRead.CreateFormat = format; textureRead.CreateUsage = Component_Image.Usages.ReadBack | Component_Image.Usages.BlitDestination; textureRead.CreateFSAA = 0; textureRead.Enabled = true; //!!!! textureRead.Result.PrepareNativeObject(); //render var image2D = new ImageUtility.Image2D(PixelFormat.Float32RGB, new Vector2I(size * 4, size * 3)); var position = Transform.Value.Position; for (int face = 0; face < 6; face++) { Vector3 dir = Vector3.Zero; Vector3 up = Vector3.Zero; //flipped switch (face) { case 0: dir = -Vector3.YAxis; up = Vector3.ZAxis; break; case 1: dir = Vector3.YAxis; up = Vector3.ZAxis; break; case 2: dir = Vector3.ZAxis; up = -Vector3.XAxis; break; case 3: dir = -Vector3.ZAxis; up = Vector3.XAxis; break; case 4: dir = Vector3.XAxis; up = Vector3.ZAxis; break; case 5: dir = -Vector3.XAxis; up = Vector3.ZAxis; break; } //!!!!renderingPipelineOverride var scene = ParentScene; var cameraEditor = scene.Mode.Value == Component_Scene.ModeEnum._2D ? scene.CameraEditor2D.Value : scene.CameraEditor.Value; if (cameraEditor == null) { cameraEditor = new Component_Camera(); } var cameraSettings = new Viewport.CameraSettingsClass(viewport, 1, 90, NearClipPlane.Value, FarClipPlane.Value, position, dir, up, ProjectionType.Perspective, 1, cameraEditor.Exposure, cameraEditor.EmissiveFactor, renderSky: RenderSky); viewport.Update(true, cameraSettings); //clear temp data viewport.RenderingContext.MultiRenderTarget_DestroyAll(); viewport.RenderingContext.DynamicTexture_DestroyAll(); texture.Result.GetRealObject(true).BlitTo(viewport.RenderingContext.CurrentViewNumber, textureRead.Result.GetRealObject(true), 0, 0); //get data var totalBytes = PixelFormatUtility.GetNumElemBytes(format) * size * size; var data = new byte[totalBytes]; unsafe { fixed(byte *pBytes = data) { var demandedFrame = textureRead.Result.GetRealObject(true).Read((IntPtr)pBytes, 0); while (RenderingSystem.CallBgfxFrame() < demandedFrame) { } } } Vector2I index = Vector2I.Zero; switch (face) { case 1: index = new Vector2I(2, 1); break; case 0: index = new Vector2I(0, 1); break; case 2: index = new Vector2I(1, 0); break; case 3: index = new Vector2I(1, 2); break; case 4: index = new Vector2I(1, 1); break; case 5: index = new Vector2I(3, 1); break; } //switch( face ) //{ //case 0: index = new Vector2I( 2, 1 ); break; //case 1: index = new Vector2I( 0, 1 ); break; //case 2: index = new Vector2I( 1, 0 ); break; //case 3: index = new Vector2I( 1, 2 ); break; //case 4: index = new Vector2I( 1, 1 ); break; //case 5: index = new Vector2I( 3, 1 ); break; //} var faceImage = new ImageUtility.Image2D(format, new Vector2I(size, size), data); //flip by X var faceImageFlip = new ImageUtility.Image2D(format, new Vector2I(size, size)); for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { var pixel = faceImage.GetPixel(new Vector2I(x, y)); faceImageFlip.SetPixel(new Vector2I(size - 1 - x, y), pixel); } } image2D.Blit(index * size, faceImageFlip); } //reset alpha channel for (int y = 0; y < image2D.Size.Y; y++) { for (int x = 0; x < image2D.Size.X; x++) { var pixel = image2D.GetPixel(new Vector2I(x, y)); pixel.W = 1.0f; image2D.SetPixel(new Vector2I(x, y), pixel); } } var destRealFileName = VirtualPathUtility.GetRealPathByVirtual(GetDestVirtualFileName()); if (!Directory.Exists(Path.GetDirectoryName(destRealFileName))) { Directory.CreateDirectory(Path.GetDirectoryName(destRealFileName)); } if (!ImageUtility.Save(destRealFileName, image2D.Data, image2D.Size, 1, image2D.Format, 1, 0, out var error)) { throw new Exception(error); } //delete Gen files var names = new string[] { "_Gen.info", "_GenEnv.dds", "_GenIrr.dds" }; foreach (var name in names) { var fileName2 = VirtualPathUtility.GetRealPathByVirtual(destRealFileName + name); if (File.Exists(fileName2)) { File.Delete(fileName2); } } } catch (Exception e) { Log.Error(e.Message); } finally { texture?.Dispose(); textureRead?.Dispose(); } processedCubemapNeedUpdate = true; }
static bool Generate(string sourceFileName, string sourceFileHash, int sourceFileSize, int specifiedSize, out string error) { var text = $"Generating cubemap \"{Path.GetFileName( sourceFileName )}\"..."; var notification = Editor.ScreenNotifications.ShowSticky(text); var destFileNameBase = GetDestFileNameBase(sourceFileName); GetDestFileNames(destFileNameBase, out var infoFileName, out var envFileName, out var irrFileName); string temporaryGeneratedFile = ""; try { var sourceRealFileName = VirtualPathUtility.GetRealPathByVirtual(sourceFileName); { //convert .image to 6 face HDR image if (Path.GetExtension(sourceRealFileName) == ".image") { var image = ResourceManager.LoadResource <Component_Image>(sourceFileName, out error); if (image == null) { return(false); } string[] loadCubeMap6Files = null; string loadFromOneFile = null; { if (image.AnyCubemapSideIsSpecified()) { if (image.AllCubemapSidesAreaSpecified()) { loadCubeMap6Files = new string[6]; for (int n = 0; n < 6; n++) { var v = image.GetLoadCubeSide(n); if (v != null) { loadCubeMap6Files[n] = v.ResourceName; } if (string.IsNullOrEmpty(loadCubeMap6Files[n]) || !VirtualFile.Exists(loadCubeMap6Files[n])) { loadCubeMap6Files = null; break; } } } } else { var v = image.LoadFile.Value; loadFromOneFile = v != null ? v.ResourceName : ""; if (string.IsNullOrEmpty(loadFromOneFile) || !VirtualFile.Exists(loadFromOneFile)) { loadFromOneFile = null; } } } if (loadFromOneFile != null) { sourceRealFileName = VirtualPathUtility.GetRealPathByVirtual(loadFromOneFile); } else if (loadCubeMap6Files != null) { temporaryGeneratedFile = Path.GetTempPath() + Guid.NewGuid().ToString() + ".hdr"; sourceRealFileName = temporaryGeneratedFile; ImageUtility.Image2D image2D = null; for (int face = 0; face < 6; face++) { if (!ImageUtility.LoadFromVirtualFile(loadCubeMap6Files[face], out var data, out var size, out _, out var format, out _, out _, out error)) { return(false); } if (image2D == null) { image2D = new ImageUtility.Image2D(PixelFormat.Float32RGB, size * new Vector2I(4, 3)); } Vector2I index = Vector2I.Zero; switch (face) { case 0: index = new Vector2I(2, 1); break; case 1: index = new Vector2I(0, 1); break; case 2: index = new Vector2I(1, 0); break; case 3: index = new Vector2I(1, 2); break; case 4: index = new Vector2I(1, 1); break; case 5: index = new Vector2I(3, 1); break; } var faceImage = new ImageUtility.Image2D(format, size, data); image2D.Blit(index * size, faceImage); } if (!ImageUtility.Save(temporaryGeneratedFile, image2D.Data, image2D.Size, 1, image2D.Format, 1, 0, out error)) { return(false); } } else { error = "The image wrong configured."; return(false); } } } int sizeEnv = 32; if (specifiedSize == 0) { //detect size if (!ImageUtility.LoadFromRealFile(sourceRealFileName, out _, out var sourceSize, out _, out _, out _, out _, out error)) { return(false); } //!!!!если кубемапа if (Math.Abs((double)sourceSize.X / (double)sourceSize.Y - 1.333333) <= 0.001) { sizeEnv = sourceSize.X / 4; } else { //!!!! sizeEnv = MathEx.NextPowerOfTwo(sourceSize.X / 3); } if (sizeEnv == 0) { sizeEnv = 1; } } else { sizeEnv = specifiedSize; } int sizeIrr = 32; var destRealFileNameBase = VirtualPathUtility.GetRealPathByVirtual(destFileNameBase); var infoRealFileName = VirtualPathUtility.GetRealPathByVirtual(infoFileName); var envRealFileName = VirtualPathUtility.GetRealPathByVirtual(envFileName); var irrRealFileName = VirtualPathUtility.GetRealPathByVirtual(irrFileName); //delete old files if (File.Exists(infoRealFileName)) { File.Delete(infoRealFileName); } if (File.Exists(envRealFileName)) { File.Delete(envRealFileName); } if (File.Exists(irrRealFileName)) { File.Delete(irrRealFileName); } var destDirectory = Path.GetDirectoryName(destRealFileNameBase); if (!Directory.Exists(destDirectory)) { Directory.CreateDirectory(destDirectory); } var irradianceValues = new List <Vector3>(); if (!GenerateFile(sourceRealFileName, false, sizeEnv, envRealFileName, irradianceValues, out error)) { return(false); } if (!GenerateFile(sourceRealFileName, true, sizeIrr, irrRealFileName, null, out error)) { return(false); } //make .info file { var block = new TextBlock(); block.SetAttribute("SourceFileHash", sourceFileHash); block.SetAttribute("SourceFileSize", sourceFileSize.ToString()); //block.SetAttribute( "SourceFileFormat", sourceFileFormat.ToString() ); for (int n = 0; n < irradianceValues.Count; n++) { block.SetAttribute("Irradiance" + n.ToString(), irradianceValues[n].ToString()); } if (!TextBlockUtility.SaveToRealFile(block, infoRealFileName, out error)) { return(false); } } } catch (Exception e) { error = e.Message; return(false); } finally { notification.Close(); try { if (File.Exists(temporaryGeneratedFile)) { File.Delete(temporaryGeneratedFile); } } catch { } } error = ""; return(true); }
public static bool Convert2DToDDS(string virtualFileName, string outputRealFileName, DDSImage.FormatEnum outputFormat, bool normalMap, bool generateMipmaps, out Vector2I sourceFileSize, out PixelFormat sourceFileFormat, out string error) { sourceFileSize = Vector2I.Zero; sourceFileFormat = PixelFormat.Unknown; if (!ImageUtility.LoadFromVirtualFile(virtualFileName, out var data, out var size, out var depth, out var format, out var numFaces, out var numMipmaps, out error)) { return(false); } sourceFileSize = size; sourceFileFormat = format; byte[] rgba = new byte[size.X * size.Y * 4]; if (format != PixelFormat.R8G8B8A8) { for (int y = 0; y < size.Y; y++) { for (int x = 0; x < size.X; x++) { byte r; byte g; byte b; byte a = 255; int offset; switch (format) { case PixelFormat.R8G8B8: offset = (y * size.X + x) * 3; r = data[offset + 2]; g = data[offset + 1]; b = data[offset + 0]; break; case PixelFormat.X8R8G8B8: offset = (y * size.X + x) * 4; r = data[offset + 2]; g = data[offset + 1]; b = data[offset + 0]; break; case PixelFormat.A8R8G8B8: offset = (y * size.X + x) * 4; a = data[offset + 3]; r = data[offset + 2]; g = data[offset + 1]; b = data[offset + 0]; break; case PixelFormat.L8: offset = (y * size.X + x); r = g = b = data[offset]; break; case PixelFormat.ShortRGB: unsafe { fixed(byte *pData = data) { ushort *pData2 = (ushort *)pData; offset = (y * size.X + x) * 3; r = (byte)((float)pData2[offset + 0] / ushort.MaxValue * 255.0f); g = (byte)((float)pData2[offset + 1] / ushort.MaxValue * 255.0f); b = (byte)((float)pData2[offset + 2] / ushort.MaxValue * 255.0f); } } break; case PixelFormat.ShortRGBA: unsafe { fixed(byte *pData = data) { ushort *pData2 = (ushort *)pData; offset = (y * size.X + x) * 4; r = (byte)((float)pData2[offset + 0] / ushort.MaxValue * 255.0f); g = (byte)((float)pData2[offset + 1] / ushort.MaxValue * 255.0f); b = (byte)((float)pData2[offset + 2] / ushort.MaxValue * 255.0f); a = (byte)((float)pData2[offset + 3] / ushort.MaxValue * 255.0f); } } break; case PixelFormat.Float32RGB: unsafe { fixed(byte *pData = data) { float *pData2 = (float *)pData; offset = (y * size.X + x) * 3; r = (byte)MathEx.Clamp((float)pData2[offset + 0] * 255.0f, 0.0f, 255.0f); g = (byte)MathEx.Clamp((float)pData2[offset + 1] * 255.0f, 0.0f, 255.0f); b = (byte)MathEx.Clamp((float)pData2[offset + 2] * 255.0f, 0.0f, 255.0f); } } break; case PixelFormat.Float32RGBA: unsafe { fixed(byte *pData = data) { float *pData2 = (float *)pData; offset = (y * size.X + x) * 4; r = (byte)MathEx.Clamp((float)pData2[offset + 0] * 255.0f, 0.0f, 255.0f); g = (byte)MathEx.Clamp((float)pData2[offset + 1] * 255.0f, 0.0f, 255.0f); b = (byte)MathEx.Clamp((float)pData2[offset + 2] * 255.0f, 0.0f, 255.0f); a = (byte)MathEx.Clamp((float)pData2[offset + 3] * 255.0f, 0.0f, 255.0f); } } break; default: error = $"Conversion from \'{format}\' format is not supported."; return(false); } //copy to rgba array offset = (y * size.X + x) * 4; rgba[offset + 0] = r; rgba[offset + 1] = g; rgba[offset + 2] = b; rgba[offset + 3] = a; } } } var image = GenerateDDS(rgba, size, outputFormat, normalMap, generateMipmaps, out error); if (image == null) { return(false); } if (!WriteToFile(outputRealFileName, image, out error)) { return(false); } error = ""; return(true); //MapFormats mapFormat = textureData.normalMap ? NormalMapFormat : BaseMapFormat; //DDSImage.FormatTypes ddsFormat = DDSImage.FormatTypes.DXT1; //switch( mapFormat ) //{ //case MapFormats.DDS_DXT1: // ddsFormat = DDSImage.FormatTypes.DXT1; // break; //case MapFormats.DDS_DXT5: // ddsFormat = DDSImage.FormatTypes.DXT5; // break; //case MapFormats.DDS_3DC: // ddsFormat = DDSImage.FormatTypes._3DC; // break; //case MapFormats.DDS_ARGB: // ddsFormat = DDSImage.FormatTypes.A8R8G8B8; // break; //} //DDSImage ddsImage = DDSImageManager.Instance.Generate( rgba, size, ddsFormat, true ); //bool oldExists = File.Exists( outputRealFullPath ); //using( FileStream stream = new FileStream( outputRealFullPath, FileMode.Create ) ) //{ // DDSImageManager.WriteFile( stream, ddsImage ); //} //createdFiles.Add( new CreatedFileItem( outputRealFullPath, oldExists ) ); //error = null; //return true; }