//private IEnumerable<Vector2d> GenerateLensSamples(int tileSize, int sqrtSampleCount) //{ // int pixelCount = tileSize * tileSize; // IEnumerator<Vector2d>[] jitteredSamplers = new IEnumerator<Vector2d>[pixelCount]; // Sampler sampler = new Sampler(); // for (int i = 0; i < pixelCount; i++) // { // jitteredSamplers[i] = sampler.GenerateJitteredSamples(MaxTotalSampleCount).GetEnumerator(); // } // for (int sample = 0; sample < MaxTotalSampleCount; sample++) // { // for (int i = 0; i < pixelCount; i++) // { // jitteredSamplers[i].MoveNext(); // yield return jitteredSamplers[i].Current; // } // } //} private void GeneratePixelSamplesTexture(int textureId, int sqrtSampleCount, int sampleCount) { GL.BindTexture(TextureTarget.Texture1D, textureId); // size of a group of samples for a single pixel int bands = 2; int textureSize = bands * sampleCount; Sampler sampler = new Sampler(); IntPtr texturePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Half)) * textureSize); unsafe { Half *row = (Half *)texturePtr; int index = 0; foreach (Vector2d sample in sampler.GenerateJitteredSamples(sqrtSampleCount)) { row[index] = (Half)(sample.X - 0.5f); index++; row[index] = (Half)(sample.Y - 0.5f); index++; } } // TODO: could be an half float or unsigned byte instead of a float // TODO: two sample pair could be stored in one 4-channel value GL.TexImage1D(TextureTarget.Texture1D, 0, PixelInternalFormat.Rg16f, sampleCount, 0, PixelFormat.Rg, PixelType.HalfFloat, texturePtr); Marshal.FreeHGlobal(texturePtr); GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexParameter(TextureTarget.Texture1D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); }
static uint GenerateHdrStarsTex(int width, int height, int starCount, float intensity, bool colorize, int seed) { uint texture = (uint)GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, texture); int bands = 3; int textureSize = bands * width * height; IList <Star> stars = Star.GenerateStars(starCount, intensity, colorize, seed); IntPtr texturePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Half)) * textureSize); unsafe { // zero out the texture Half zero = (Half)0.0; for (int y = 0; y < height; y++) { Half *row = (Half *)texturePtr + bands * y * width; int index = 0; for (int x = 0; x < width; x++) { for (int band = 0; band < bands; band++) { row[index++] = zero; } } } // put the stars into the image Half *image = (Half *)texturePtr; foreach (var star in stars) { int x = (int)(star.Position.X * width); int y = (int)(star.Position.Y * height); int index = bands * (y * width + x); image[index] = (Half)star.Color.X; image[index + 1] = (Half)star.Color.Y; image[index + 2] = (Half)star.Color.Z; } } GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb16f, width, height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.HalfFloat, texturePtr); Marshal.FreeHGlobal(texturePtr); //GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); //GL.Ext.GenerateMipmap(GenerateMipmapTarget.Texture2D); return(texture); }
public unsafe static void ToInt8(Half *x, int length, sbyte[] y) { var Threads = Environment.ProcessorCount; var TaskPart = length / Threads; var TaskRemainder = length % Threads; Parallel.For(0, Threads, (int i) => { var start = TaskPart * i; var end = start + TaskPart; for (int j = start; j < end; j++) { y[j] = (sbyte)x[j]; } }); var start_ = TaskPart * Threads; var end_ = start_ + TaskRemainder; for (int j = start_; j < end_; j++) { y[j] = (sbyte)x[j]; } }
/// <summary> /// Takes a NormalDepth texture and creates a normal- and a depth-bitmap /// </summary> /// <param name="normal">The normal-bitmap</param> /// <param name="depth">The depth-bitmap</param> public unsafe void UploadNormalDepthBitmapsWpf(out WriteableBitmap normal, out WriteableBitmap depth) { //Check current format if (m_format != GraphicsHelper.DEFAULT_TEXTURE_FORMAT_NORMAL_DEPTH) { throw new SeeingSharpGraphicsException("Invalid format for getting NormalDepth-Values (" + m_format + ")!"); } //Upload the texture CopyTextureToStagingResource(true); //Read the data into the .Net data block SharpDX.DataBox dataBox = m_device.DeviceImmediateContextD3D11.MapSubresource( m_copyHelperTextureStaging, 0, D3D11.MapMode.Read, D3D11.MapFlags.None); //Create the output bitmaps normal = new WriteableBitmap(m_width, m_height, 96, 96, System.Windows.Media.PixelFormats.Bgra32, null); depth = new WriteableBitmap(m_width, m_height, 96, 96, System.Windows.Media.PixelFormats.Bgra32, null); try { //Read the values from Texture into bitmapsa Half *pointr = (Half *)dataBox.DataPointer.ToPointer(); int rowPitchSource = dataBox.RowPitch / 2; int rowSource = normal.BackBufferStride / 4; normal.Lock(); depth.Lock(); int *normalBitmapBuffer = (int *)normal.BackBuffer.ToPointer(); int *depthBitmapBuffer = (int *)depth.BackBuffer.ToPointer(); for (int loopY = 0; loopY < m_height; loopY++) { for (int loopX = 0; loopX < m_width; loopX++) { //Calculate the pointer int position = (loopY * rowPitchSource) + (loopX * 4); //Read values from texture Half valueR = pointr[position]; Half valueG = pointr[position + 1]; Half valueB = pointr[position + 2]; Half valueDepth = pointr[position + 3]; //Calculate the Values for the Colors int colorR = (int)Math.Abs(valueR * 255); int colorG = (int)Math.Abs(valueG * 255); int colorB = (int)Math.Abs(valueB * 255); int colorDepthVal = (int)Math.Abs(valueDepth); colorDepthVal = 255 - (colorDepthVal > 255 ? 255 : colorDepthVal < 0 ? 0 : colorDepthVal); colorR = colorR > 255 ? 255 : colorR < 0 ? 0 : colorR; colorG = colorG > 255 ? 255 : colorG < 0 ? 0 : colorG; colorB = colorB > 255 ? 255 : colorB < 0 ? 0 : colorB; //Create Colors Color colorNormal = Color.FromArgb(255, colorR, colorG, colorB); Color colorDepth = Color.FromArgb(255, colorDepthVal, colorDepthVal, colorDepthVal); int normalColorData = colorNormal.A << 24; normalColorData |= colorNormal.R << 16; normalColorData |= colorNormal.G << 8; normalColorData |= colorNormal.B << 0; int depthColorData = colorDepth.A << 24; depthColorData |= colorDepth.R << 16; depthColorData |= colorDepth.G << 8; depthColorData |= colorDepth.B << 0; normalBitmapBuffer[loopY * rowSource + (loopX)] = normalColorData; depthBitmapBuffer[loopY * rowSource + loopX] = depthColorData; } } normal.AddDirtyRect(new System.Windows.Int32Rect(0, 0, m_width, m_height)); depth.AddDirtyRect(new System.Windows.Int32Rect(0, 0, m_width, m_height)); normal.Unlock(); normal.Freeze(); depth.Unlock(); depth.Freeze(); } finally { m_device.DeviceImmediateContextD3D11.UnmapSubresource(m_copyHelperTextureStaging, 0); } }
private void GenerateLensSamplesTextures(int textureId, int totalSampleCount, int tileSize) { // size of a group of samples for a single pixel int bands = 2; int textureSize = bands * totalSampleCount * tileSize * tileSize; //IEnumerable<Vector2d> samples = GenerateLensSamples(tileSize, (int)Math.Sqrt(MaxTotalSampleCount)).GetEnumerator(); int sqrtTotalSampleCount = (int)Math.Sqrt(totalSampleCount); Vector2[, ,] samples = new Vector2[tileSize, tileSize, totalSampleCount]; Sampler sampler = new Sampler(); for (int y = 0; y < tileSize; y++) { for (int x = 0; x < tileSize; x++) { IEnumerable <Vector2> pixelSamples = sampler.CreateLensSamplesFloat(sqrtTotalSampleCount, ShuffleLensSamples); int z = 0; foreach (Vector2 sample in pixelSamples) { samples[x, y, z] = sample; z++; } } } GL.BindTexture(TextureTarget.Texture3D, textureId); IntPtr texturePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Half)) * textureSize); unsafe { int zStride = bands * tileSize * tileSize; for (int y = 0; y < tileSize; y++) { for (int x = 0; x < tileSize; x++) { Half *row = (Half *)texturePtr + bands * (y * tileSize + x); int index = 0; // Z dimension for (int sample = 0; sample < totalSampleCount; sample++) { Vector2 lensPos = samples[x, y, sample]; row[index] = (Half)lensPos.X; row[index + 1] = (Half)lensPos.Y; index += zStride; } } } } // TODO: could be an half float or unsigned byte instead of a float // TODO: two sample pair could be stored in one 4-channel value GL.TexImage3D(TextureTarget.Texture3D, 0, PixelInternalFormat.Rg16f, tileSize, tileSize, totalSampleCount, 0, PixelFormat.Rg, PixelType.HalfFloat, texturePtr); Marshal.FreeHGlobal(texturePtr); GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture3D, TextureParameterName.TextureWrapR, (int)TextureWrapMode.Clamp); }
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 PostRenderCommand(Vector position, float z_other, Vector bound, float rotate, Vector scale, HalfVector anchor, ByteVec4 color, bool vertical_flip, bool horizon_flip) { /*-----------------CURRENT VERSION------------------ - * anchor(Hlaf) color(byte) modelMatrix * vec2(2) vec4(4) Matrix3x2(6) */ var is_xflip = Math.Sign(scale.X); var is_yflip = Math.Sign(scale.Y); //adjust scale transform which value is negative horizon_flip = horizon_flip | (is_xflip < 0); vertical_flip = vertical_flip | (is_yflip < 0); float scalex = is_xflip * scale.X * bound.X; float scaley = is_yflip * scale.Y * bound.Y; //Create ModelMatrix float cosa = (float)Math.Cos(rotate); float sina = (float)Math.Sin(rotate); Matrix3x2 model = Matrix3x2.Zero; model.Row0.X = cosa * scalex; model.Row0.Y = -sina * scalex; model.Row1.X = sina * scaley; model.Row1.Y = cosa * scaley; model.Row2.X = position.X - RenderKernel.SB_WIDTH / 2f; model.Row2.Y = -position.Y + RenderKernel.SB_HEIGHT / 2f; unsafe { //Anchor write fixed(byte *ptr = &PostData[_currentPostBaseIndex]) { //anchor int *hpv = (int *)(ptr + 0); *hpv = *(int *)&anchor; //color int *ip = (int *)(ptr + 4); *ip = *(int *)&color; //flip write Half *hp = (Half *)(ptr + 8); hp[0] = horizon_flip ? HalfNegativeOne : HalfOne; hp[1] = vertical_flip ? HalfNegativeOne : HalfOne; var copyLen = 2 * 3 * sizeof(float); var basePtr = (byte *)&model.Row0.X; for (int i = 0; i < copyLen; i++) { ptr[i + 12] = *(basePtr + i); } } } CurrentPostCount++; _currentPostBaseIndex += _VertexSize; if (CurrentPostCount >= Capacity) { FlushDraw(); } }