/// <summary> /// Loads the LTC table used in Unity /// </summary> /// <returns></returns> Texture2D LoadUnityLTC() { uint S = (uint)UnityEngine.Experimental.Rendering.HDPipeline.LTCAreaLight.k_LtcLUTResolution; PixelsBuffer content = new PixelsBuffer(S * S * 16); using (BinaryWriter W = content.OpenStreamWrite()) { for (uint Y = 0; Y < S; Y++) { for (uint X = 0; X < S; X++) { uint i = S * Y + X; float m11 = (float)UnityEngine.Experimental.Rendering.HDPipeline.LTCAreaLight.s_LtcGGXMatrixData[i, 0]; float m13 = (float)UnityEngine.Experimental.Rendering.HDPipeline.LTCAreaLight.s_LtcGGXMatrixData[i, 2]; float m22 = (float)UnityEngine.Experimental.Rendering.HDPipeline.LTCAreaLight.s_LtcGGXMatrixData[i, 4]; float m31 = (float)UnityEngine.Experimental.Rendering.HDPipeline.LTCAreaLight.s_LtcGGXMatrixData[i, 6]; W.Write(m11); W.Write(m13); W.Write(m22); W.Write(m31); } } } Texture2D T = new Texture2D(m_device, S, S, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, false, new PixelsBuffer[] { content }); return(T); }
void BuildNoiseTextures() { PixelsBuffer Content = new PixelsBuffer(NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * 4); PixelsBuffer Content4D = new PixelsBuffer(NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * 16); WMath.SimpleRNG.SetSeed(521288629, 362436069); float4 V = float4.Zero; using (BinaryWriter W = Content.OpenStreamWrite()) { using (BinaryWriter W2 = Content4D.OpenStreamWrite()) { for (int Z = 0; Z < NOISE_SIZE; Z++) { for (int Y = 0; Y < NOISE_SIZE; Y++) { for (int X = 0; X < NOISE_SIZE; X++) { V.Set((float)WMath.SimpleRNG.GetUniform(), (float)WMath.SimpleRNG.GetUniform(), (float)WMath.SimpleRNG.GetUniform(), (float)WMath.SimpleRNG.GetUniform()); W.Write(V.x); W2.Write(V.x); W2.Write(V.y); W2.Write(V.z); W2.Write(V.w); } } } } } m_Tex_Noise = new Texture3D(m_Device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, PIXEL_FORMAT.R8_UNORM, false, false, new PixelsBuffer[] { Content }); m_Tex_Noise4D = new Texture3D(m_Device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, PIXEL_FORMAT.RGBA8_UNORM, false, false, new PixelsBuffer[] { Content4D }); }
private void btnDrawPolygon_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.MistyRose; //populate polygon coordinate data double[] coordinates = new double[] { 30, 300, 150, 40, 300, 260, 130, 200, //30, 300 //the last point is omitted to show that the end point is important //for rendering stroke }; //draw content drawer.DrawPolygon(fill, coordinates); //show to screen DisplayBuffer(buffer); }
private void btnBufferInBufferDraw_Click(object sender, EventArgs e) { //create & render to main buffer PixelsBuffer buffer = new PixelsBuffer(width, height); DrawStar(buffer, Colors.Red, Colors.White); //create a sub view (50, 50, 100, 100) - inversed PixelsBuffer view = buffer.CreateView(50, 250, 100, 100, true); DrawStar(view, Colors.Blue, Colors.YellowGreen); //create a sub view (50, 50, 100, 100) view = buffer.CreateView(250, 150, 100, 100); DrawStar(view, Colors.Goldenrod, Colors.LemonChiffon); //show to screen DisplayBuffer(buffer); #region Description string msg = "This example demonstrates that logical views with different coordinate systems can be attached to the same pixel buffer"; txtDescription.Text = msg; #endregion }
private void btnDrawPath_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.MistyRose; //create path DrawingPath path = new DrawingPath(); path.MoveTo(200, 100); path.CurveTo(200, 350, 340, 30, 360, 200); path.CurveTo(200, 100, 40, 200, 60, 30); //draw content drawer.Rotate(15); drawer.Scale(0.3, 0.3); drawer.DrawPath(fill, path); //show to screen DisplayBuffer(buffer); }
// ======= VIRTUAL METHODS #region PrepareBuffer /// <summary> /// Preparing buffer and internal data for using /// </summary> /// <param name="buffer">buffer</param> protected virtual void PrepareBuffer(PixelsBuffer buffer) { //automatically create a new boundary to match this buffer if (mBuffer == null) { //mBoundary = Boundary.Empty; DestBufferWidth = 0; DestBufferHeight = 0; BufferStride = 0; BufferStartOffset = 0; BufferData = null; } else { //mBoundary = new Boundary(mBuffer.Width, mBuffer.Height); DestBufferWidth = mBuffer.Width; DestBufferHeight = mBuffer.Height; BufferStride = mBuffer.Stride; BufferStartOffset = mBuffer.StartOffset; BufferData = mBuffer.Data; //mPixelRenderer.PixelBuffer = mBuffer; } if ((Rows == null) || (Rows.Length < DestBufferHeight + 1)) { Rows = new RowData[DestBufferHeight + 1]; } SetClip(0, 0, DestBufferWidth, DestBufferHeight); }
/// <summary> /// Draw a frame around the buffer from (0,0) to (width, height) /// </summary> void DrawFrame(PixelsBuffer buffer, Color color) { int idx = 0; //pixel index //draw left, right lines for (int y = 0; y < buffer.Height; y++) { //left idx = buffer.StartOffset + buffer.Stride * y;// buffer.GetPixelIndex(0, y); buffer.Data[idx] = color.Data; //right idx = buffer.StartOffset + buffer.Stride * y + buffer.Width - 1;// buffer.GetPixelIndex(buffer.Width - 1, y); buffer.Data[idx] = color.Data; } //draw top, bottom lines for (int x = 0; x < buffer.Width; x++) { //top idx = buffer.StartOffset + x;// buffer.GetPixelIndex(x, 0); buffer.Data[idx] = color.Data; //bottom idx = buffer.StartOffset + (buffer.Height - 1) * buffer.Stride + x;// buffer.GetPixelIndex(x, buffer.Height - 1); buffer.Data[idx] = color.Data; } }
/// <summary> /// Reads back a lobe texture histogram into an array /// </summary> /// <param name="_texHistogram_CPU"></param> /// <param name="_scatteringOrder"></param> /// <returns></returns> public static double[,] HistogramTexture2Array(Texture2D _texHistogram_CPU, int _scatteringOrder) { int scattMin = _scatteringOrder - 1; // Because scattering order 1 is actually stored in first slice of the texture array int scattMax = scattMin + 1; // To simulate a single scattering order // int scattMax = MAX_SCATTERING_ORDER; // To simulate all scattering orders accumulated int W = _texHistogram_CPU.Width; int H = _texHistogram_CPU.Height; double[,] histogramData = new double[W, H]; for (int scatteringOrder = scattMin; scatteringOrder < scattMax; scatteringOrder++) { PixelsBuffer Content = _texHistogram_CPU.Map(0, scatteringOrder); using (BinaryReader R = Content.OpenStreamRead()) for (int Y = 0; Y < H; Y++) { for (int X = 0; X < W; X++) { histogramData[X, Y] += W * H * R.ReadSingle(); } } Content.CloseStream(); _texHistogram_CPU.UnMap(0, scatteringOrder); } return(histogramData); }
/// <summary> /// Obtains a rendering buffer from a gdi+ System.Drawing.Bitmap /// </summary> public static PixelsBuffer GetBuffer(Image source) { PixelsBuffer result = new PixelsBuffer(source.Width, source.Height, source.Width); DrawBitmapToBuffer(source, result); return(result); }
private void Build3DDensityField() { PixelsBuffer DensityField = new PixelsBuffer(DENSITY_FIELD_SIZE * DENSITY_FIELD_SIZE * DENSITY_FIELD_HEIGHT); byte D; float3 P; float3 C = new float3(0.5f, 0.5f, 0.5f); using (System.IO.BinaryWriter W = DensityField.OpenStreamWrite()) for (int X = 0; X < DENSITY_FIELD_SIZE; X++) { P.x = (0.5f + X) / DENSITY_FIELD_SIZE; for (int Y = 0; Y < DENSITY_FIELD_HEIGHT; Y++) { P.y = (0.5f + Y) / DENSITY_FIELD_HEIGHT; for (int Z = 0; Z < DENSITY_FIELD_SIZE; Z++) { P.z = (0.5f + Z) / DENSITY_FIELD_SIZE; // D = 0; // Empty for now: photons should go straight through! D = (byte)((P - C).LengthSquared < 0.125f ? 255 : 0); W.Write(D); } } } Reg(m_Tex_DensityField = new Texture3D(m_Device, DENSITY_FIELD_SIZE, DENSITY_FIELD_HEIGHT, DENSITY_FIELD_SIZE, 1, PIXEL_FORMAT.R8_UNORM, false, false, new PixelsBuffer[] { DensityField })); DensityField.Dispose(); }
/// <summary> /// Helper method to display result from a pixel buffer to Original view /// </summary> void DisplayOriginal(PixelsBuffer buffer) { if (bmpOrg != null) { bmpOrg.Dispose(); } bmpOrg = Cross.Helpers.BufferToBitmap.GetBitmap(buffer, System.Drawing.Imaging.PixelFormat.Format32bppArgb); pbOriginal.Image = bmpOrg; }
private void fmFill_Load(object sender, EventArgs e) { if (!DesignMode) { buffer = new PixelsBuffer(w, h); drawer = new Drawer(buffer); Draw(); } }
/// <summary> /// Helper method to display result from a pixel buffer /// </summary> void DisplayBuffer(PixelsBuffer buffer) { if (bmp != null) { bmp.Dispose(); } bmp = Cross.Helpers.BufferToBitmap.GetBitmap(buffer, System.Drawing.Imaging.PixelFormat.Format32bppArgb); pbView.Image = bmp; }
/// <summary> /// Draw a diagonal line with the specified color from (0,0) to (width, height) /// </summary> void DrawLine(PixelsBuffer buffer, Color color) { int idx = 0; //pixel index for (int i = 0; i < buffer.Height; i++) { idx = buffer.StartOffset + i * buffer.Stride + i; // buffer.GetPixelIndex(i, i); buffer.Data[idx] = color.Data; } }
public Texture2D Image2Texture(int _Width, int _Height, byte[] _Content) { using (PixelsBuffer Buff = new PixelsBuffer(_Content.Length)) { using (System.IO.BinaryWriter W = Buff.OpenStreamWrite()) W.Write(_Content); return(Image2Texture(_Width, _Height, Buff)); } }
/// <summary> /// Obtain a Bitmap from <see cref="RenderingBuffer"/> /// </summary> public static Bitmap GetBitmap(PixelsBuffer source, Bitmap.Config config = null) { var bmp = Bitmap.CreateBitmap(Array.ConvertAll <uint, int>(source.Data, new Converter <uint, int>(x => (int)x)), source.StartOffset, source.Stride, source.Width, source.Height, Bitmap.Config.Argb8888); if (config != null && !config.Equals(Bitmap.Config.Argb8888)) { var tmp = ConvertConfig(bmp, config); bmp.Dispose(); bmp = tmp; } return(bmp); }
private void Draw(ImageView imageView, int times) { var start = DateTime.Now; PixelsBuffer buffer = new PixelsBuffer(600, 600); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.Transparent); //create fill for drawing Fill fill = new Fill(Colors.Transparent); //fill.Opacity = 0.3; //draw content var coords1 = GetPath(1); var coords2 = GetPath(0); var coords3 = GetPath(2); var path = GetPath(); var startDraw = DateTime.Now; int step = 5; for (int i = 0; i < times; i++) { //drawer.DrawRectangle(fill, 10, 10, 300, 300); //drawer.DrawEllipse(fill, 200, 200, 120, 200); //drawer.DrawPolygon(fill, coords1); //drawer.DrawPolygon(fill, coords2); //drawer.DrawPolygon(fill, coords3); //draw content //drawer.Rotate(15); //drawer.Scale(0.3, 0.3); //drawer.DrawPath(fill, path); var margin = i / 10 * step; PixelsBuffer view = buffer.CreateView(margin, margin, buffer.Width - margin * 2, buffer.Height - margin * 2, true); DrawFrame(view, Colors.OrangeRed); DrawLine(view, Colors.Olive); } DrawLion(buffer, 200, 200); if (bmp != null) { bmp.Dispose(); } bmp = BufferToBitmap.GetBitmap(buffer); //show to screen var icon = BitmapFactory.DecodeResource(this.Resources, Resource.Drawable.Icon); imageView.SetImageBitmap(BufferToBitmap.Overlay(new Bitmap[] { icon, bmp })); Android.Util.Log.Debug("Draw " + times, "Draw: " + (DateTime.Now - startDraw).TotalSeconds.ToString() + " Total: " + (DateTime.Now - start).TotalSeconds.ToString()); }
/// <summary> /// Render a star shape to buffer /// </summary> void DrawStar(PixelsBuffer buffer, Color color, Color background) { IDrawer drawer = new Drawer(buffer); drawer.Clear(background); Fill fill = new Fill(color); double[] coordinates = TestFactory.Star(); TestFactory.Scale(coordinates, 2.0); //drawer.DrawRectangle(stroke, 0, 0, buffer.Width, buffer.Height); drawer.DrawPolygon(fill, coordinates); }
public static void DrawBitmapToBuffer(Bitmap source, PixelsBuffer buffer) { //make sure we have a ABGR Bitmap, same as PixelFormat.Format32bppArgb var bmp = ConvertConfig(source, Bitmap.Config.Argb8888); //copy Bitmap's data to buffer IntPtr ptr = bmp.LockPixels(); int size = bmp.RowBytes * bmp.Height; byte[] tmpBuffer = new byte[bmp.Width * bmp.Height * 4]; System.Runtime.InteropServices.Marshal.Copy(ptr, tmpBuffer, 0, size); bmp.UnlockPixels(); //copy to pixel buffer buffer.FromBytes(tmpBuffer, PixelFormats.Bgra); }
/// <summary> /// Helper method to display result from a pixel buffer to After 3 view /// </summary> void DisplayAfter3(PixelsBuffer buffer) { if (bmpAfter3 != null) { bmpAfter3.Dispose(); } if (buffer != null) { bmpAfter3 = Cross.Helpers.BufferToBitmap.GetBitmap(buffer, System.Drawing.Imaging.PixelFormat.Format32bppArgb); pbAfter3.Image = bmpAfter3; } else { pbAfter3.Image = null; } }
private void btnDrawRoundRect_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.DarkOrange; //draw content drawer.DrawRoundedRectangle(fill, 50, 50, 300, 200, 15, 15); //show to screen DisplayBuffer(buffer); }
private void btnDrawEllipse_Click(object sender, EventArgs e) { //create a new drawing context PixelsBuffer buffer = new PixelsBuffer(400, 400); IDrawer drawer = new Drawer(buffer); drawer.Clear(Colors.White); //create fill for drawing Fill fill = Fills.Yellow; //draw content drawer.DrawEllipse(fill, 200, 200, 180, 100); //show to screen DisplayBuffer(buffer); }
private void btnDrawStar_Click(object sender, EventArgs e) { //create buffer PixelsBuffer buffer = new PixelsBuffer(width, height); //render DrawStar(buffer, Colors.Red, Colors.White); //show to screen DisplayBuffer(buffer); #region Description string msg = "Create new buffer, then draw a star"; txtDescription.Text = msg; #endregion }
void BuildFont() { string charSet = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~éèêëôöà çÔÖÂÊÉœûüù"; m_fontRectangles = new Rectangle[charSet.Length]; for (int charIndex = 0; charIndex < charSet.Length; charIndex++) { char C = charSet[charIndex]; int index = (int)C; m_char2Index[index] = charIndex; } // Load atlas & rectangles using (ImageUtility.ImageFile file = new ImageUtility.ImageFile(new FileInfo("Atlas.png"))) { ImageUtility.ImageFile file2 = new ImageUtility.ImageFile(file, ImageUtility.PIXEL_FORMAT.RGBA8); using (ImageUtility.ImagesMatrix M = new ImageUtility.ImagesMatrix(file2, ImageUtility.ImagesMatrix.IMAGE_TYPE.sRGB)) { m_tex_FontAtlas = new Texture2D(m_device, M, ImageUtility.COMPONENT_FORMAT.UNORM_sRGB); } } using (FileStream S = new FileInfo("Atlas.rect").OpenRead()) using (BinaryReader R = new BinaryReader(S)) { // Read both CPU and GPU versions float recW = 1.0f / m_tex_FontAtlas.Width; float recH = 1.0f / m_tex_FontAtlas.Height; using (PixelsBuffer content = new PixelsBuffer((uint)(16 * m_fontRectangles.Length))) { using (BinaryWriter W = content.OpenStreamWrite()) { for (int i = 0; i < m_fontRectangles.Length; i++) { m_fontRectangles[i].X = R.ReadInt32(); m_fontRectangles[i].Y = R.ReadInt32(); m_fontRectangles[i].Width = R.ReadInt32(); m_fontRectangles[i].Height = R.ReadInt32(); W.Write(recW * (float)m_fontRectangles[i].X); W.Write(recH * (float)m_fontRectangles[i].Y); W.Write(recW * (float)m_fontRectangles[i].Width); W.Write(recH * (float)m_fontRectangles[i].Height); } } m_tex_FontRectangle = new Texture2D(m_device, (uint)m_fontRectangles.Length, 1, 1, 1, ImageUtility.PIXEL_FORMAT.RGBA32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, false, new PixelsBuffer[] { content }); } } }
private void btnDrawPixels_Click(object sender, EventArgs e) { //create buffer PixelsBuffer buffer = new PixelsBuffer(width, height); //render to buffer DrawLine(buffer, Colors.Red); DrawFrame(buffer, Colors.Red); //show to screen DisplayBuffer(buffer); #region Description string msg = "Create new buffer, then manually set pixels to buffer to render a rectangular frame around the buffer and a diagonal line from point (0,0) to point (width, height)"; txtDescription.Text = msg; #endregion }
private void btnBufferInBuffer_Click(object sender, EventArgs e) { //create main buffer PixelsBuffer buffer = new PixelsBuffer(width, height); //create a sub view (100 pixels margin) int margin = 100; #region Approach 1 //calculate new view's parameter by hand //then attach the new view to main buffer /* * int viewStride = -buffer.Stride; //inverse coordinate system of view * int viewOffset = buffer.GetPixelIndex(margin, margin); * PixelBuffer view = new PixelBuffer(); * view.Attach(buffer, width - margin * 2, height - margin * 2, viewStride, viewOffset); */ #endregion #region Approach 2 //a much easier way to create sub-view PixelsBuffer view = buffer.CreateView(margin, margin, width - margin * 2, height - margin * 2, true); #endregion //render to main buffer DrawLine(buffer, Colors.Red); DrawFrame(buffer, Colors.Red); //render to sub view DrawLine(view, Colors.Blue); DrawFrame(view, Colors.Blue); //show to screen DisplayBuffer(buffer); #region Description string msg = "This example creates a main buffer, render pixels to it. Then, create a sub-view with inversed y-axis, and render to this view."; txtDescription.Text = msg; #endregion }
private void FFT_CPUInOut(Complex[,] _input, Complex[,] _output, float _sign) { try { ////////////////////////////////////////////////////////////////////////// // Load initial content PixelsBuffer loadingBuffer = m_texBufferCPU.MapWrite(0, 0); System.IO.BinaryWriter W = loadingBuffer.OpenStreamWrite(); for (int Y = 0; Y < m_size; Y++) { for (int X = 0; X < m_size; X++) { W.Write((float)_input[X, Y].r); W.Write((float)_input[X, Y].i); } } loadingBuffer.CloseStream(); m_texBufferCPU.UnMap(loadingBuffer); m_texBufferIn.CopyFrom(m_texBufferCPU); ////////////////////////////////////////////////////////////////////////// // Apply multiple shader passes FFT_GPUInOut(_sign); ////////////////////////////////////////////////////////////////////////// // Read back content m_texBufferCPU.CopyFrom(m_texBufferOut); PixelsBuffer resultBuffer = m_texBufferCPU.MapRead(0, 0); System.IO.BinaryReader R = resultBuffer.OpenStreamRead(); for (int Y = 0; Y < m_size; Y++) { for (int X = 0; X < m_size; X++) { _output[X, Y].Set(R.ReadSingle(), R.ReadSingle()); } } resultBuffer.CloseStream(); m_texBufferCPU.UnMap(resultBuffer); } catch (Exception _e) { throw new Exception("An error occurred while performing the FFT!", _e); } }
void DrawLion(PixelsBuffer buffer, int x, int y) { //create a new drawing context //PixelBuffer buffer = new PixelBuffer(400, 400); IDrawer drawer = new Drawer(buffer); //get coordinates and colors double[][] polygons = LionPathHelper.GetLionPolygons(); Cross.Drawing.Color[] colors = LionPathHelper.GetLionColors(); //iterate all polygons and draw them double[] coordinates = null; drawer.Translate(x, y); for (int i = 0; i < polygons.Length; i++) { coordinates = polygons[i]; Fill fill = new Fill(colors[i]); drawer.DrawPolygon(fill, coordinates); } }
// ACTUALLY, THESE ARE GENERATED IN MATHEMATICA NOW!! // // const uint COS_THETA_SUBDIVS_COUNT = 128; // const uint ROUGHNESS_SUBDIVS_COUNT = 128; // // float[,] m_GGX_E = new float[COS_THETA_SUBDIVS_COUNT,ROUGHNESS_SUBDIVS_COUNT]; // float[] m_GGX_Eavg = new float[ROUGHNESS_SUBDIVS_COUNT]; // // void BuildMSBRDF( DirectoryInfo _targetDirectory ) { // // FileInfo MSBRDFFileName = new FileInfo( Path.Combine( _targetDirectory.FullName, "MSBRDF_E" + COS_THETA_SUBDIVS_COUNT + "x" + ROUGHNESS_SUBDIVS_COUNT + ".float" ) ); // FileInfo MSBRDFFileName2 = new FileInfo( Path.Combine( _targetDirectory.FullName, "MSBRDF_Eavg" + ROUGHNESS_SUBDIVS_COUNT + ".float" ) ); // // #if PRECOMPUTE_BRDF // // ACTUALLY, THESE ARE GENERATED IN MATHEMATICA NOW!! // Don't expect this code to work! // // { // const uint PHI_SUBDIVS_COUNT = 2*512; // const uint THETA_SUBDIVS_COUNT = 64; // // const float dPhi = Mathf.TWOPI / PHI_SUBDIVS_COUNT; // const float dTheta = Mathf.HALFPI / THETA_SUBDIVS_COUNT; // const float dMu = 1.0f / THETA_SUBDIVS_COUNT; // // string dumpMathematica = "{"; // for ( uint Y=0; Y < ROUGHNESS_SUBDIVS_COUNT; Y++ ) { // // //Y = 5; // // float m = (float) Y / (ROUGHNESS_SUBDIVS_COUNT-1); // float m2 = Math.Max( 0.01f, m*m ); // // float m2 = Math.Max( 0.01f, (float) Y / (ROUGHNESS_SUBDIVS_COUNT-1) ); // // float m = Mathf.Sqrt( m2 ); // // // dumpMathematica += "{ "; // Start a new roughness line // for ( uint X=0; X < COS_THETA_SUBDIVS_COUNT; X++ ) { // // //X = 17; // // float cosThetaO = (float) X / (COS_THETA_SUBDIVS_COUNT-1); // float sinThetaO = Mathf.Sqrt( 1 - cosThetaO*cosThetaO ); // // float NdotV = cosThetaO; // // float integral = 0.0f; // // float integralNDF = 0.0f; // for ( uint THETA=0; THETA < THETA_SUBDIVS_COUNT; THETA++ ) { // // float thetaI = Mathf.HALFPI * (0.5f+THETA) / THETA_SUBDIVS_COUNT; // // float cosThetaI = Mathf.Cos( thetaI ); // // float sinThetaI = Mathf.Sin( thetaI ); // // // Use cosine-weighted sampling // float sqCosThetaI = (0.5f+THETA) / THETA_SUBDIVS_COUNT; // float cosThetaI = Mathf.Sqrt( sqCosThetaI ); // float sinThetaI = Mathf.Sqrt( 1 - sqCosThetaI ); // // float NdotL = cosThetaI; // // for ( uint PHI=0; PHI < PHI_SUBDIVS_COUNT; PHI++ ) { // float phi = Mathf.TWOPI * PHI / PHI_SUBDIVS_COUNT; // // // Compute cos(theta_h) = Omega_h.N where Omega_h = (Omega_i + Omega_o) / ||Omega_i + Omega_o|| is the half vector and N the surface normal // float cosThetaH = (cosThetaI + cosThetaO) / Mathf.Sqrt( 2 * (1 + cosThetaO * cosThetaI + sinThetaO * sinThetaI * Mathf.Cos( phi )) ); // // float3 omega_i = new float3( sinThetaI * Mathf.Cos( phi ), sinThetaI * Mathf.Sin( phi ), cosThetaI ); // // float3 omega_o = new float3( sinThetaO, 0, cosThetaO ); // // float3 omega_h = (omega_i + omega_o).Normalized; // // float cosThetaH = omega_h.z; // // // Compute GGX NDF // float den = 1 - cosThetaH*cosThetaH * (1 - m2); // float NDF = m2 / (Mathf.PI * den*den); // // // Compute Smith shadowing/masking // float Smith_i_den = NdotL + Mathf.Sqrt( m2 + (1-m2) * NdotL*NdotL ); // // // Full BRDF is thus... // float GGX = NDF / Smith_i_den; // // // integral += GGX * cosThetaI * sinThetaI; // integral += GGX; // } // // // integralNDF += Mathf.TWOPI * m2 * cosThetaI * sinThetaI / (Mathf.PI * Mathf.Pow( cosThetaI*cosThetaI * (m2 - 1) + 1, 2.0f )); // } // // // Finalize // float Smith_o_den = NdotV + Mathf.Sqrt( m2 + (1-m2) * NdotV*NdotV ); // integral /= Smith_o_den; // // // integral *= dTheta * dPhi; // integral *= 0.5f * dMu * dPhi; // Cosine-weighted sampling has a 0.5 factor! // // integralNDF *= dTheta; // // m_GGX_E[X,Y] = integral; // dumpMathematica += "{ " + cosThetaO + ", " + m + ", " + integral + "}, "; // } // } // // dumpMathematica = dumpMathematica.Remove( dumpMathematica.Length-2 ); // Remove last comma // dumpMathematica += " };"; // // // Dump as binary // using ( FileStream S = MSBRDFFileName.Create() ) // using ( BinaryWriter W = new BinaryWriter( S ) ) { // for ( uint Y=0; Y < ROUGHNESS_SUBDIVS_COUNT; Y++ ) // for ( uint X=0; X < COS_THETA_SUBDIVS_COUNT; X++ ) // W.Write( m_GGX_E[X,Y] ); // } // // ////////////////////////////////////////////////////////////////////////// // // Compute average irradiance based on roughness, re-using the previously computed results // const uint THETA_SUBDIVS_COUNT2 = 512; // // float dTheta2 = Mathf.HALFPI / THETA_SUBDIVS_COUNT2; // // for ( uint X=0; X < ROUGHNESS_SUBDIVS_COUNT; X++ ) { // // float integral = 0.0f; // for ( uint THETA=0; THETA < THETA_SUBDIVS_COUNT2; THETA++ ) { // float thetaO = Mathf.HALFPI * (0.5f+THETA) / THETA_SUBDIVS_COUNT2; // float cosThetaO = Mathf.Cos( thetaO ); // float sinThetaO = Mathf.Sin( thetaO ); // // // Sample previously computed table // float i = cosThetaO * COS_THETA_SUBDIVS_COUNT; // uint i0 = Math.Min( COS_THETA_SUBDIVS_COUNT-1, (uint) Mathf.Floor( i ) ); // uint i1 = Math.Min( COS_THETA_SUBDIVS_COUNT-1, i0 + 1 ); // float E = (1-i) * m_GGX_E[i0,X] + i * m_GGX_E[i1,X]; // // integral += E * cosThetaO * sinThetaO; // } // // // Finalize // integral *= Mathf.TWOPI * dTheta2; // // m_GGX_Eavg[X] = integral; // } // // // Dump as binary // using ( FileStream S = MSBRDFFileName2.Create() ) // using ( BinaryWriter W = new BinaryWriter( S ) ) { // for ( uint X=0; X < ROUGHNESS_SUBDIVS_COUNT; X++ ) // W.Write( m_GGX_Eavg[X] ); // } // } // // #endif // // // // Build irradiance complement texture // // using ( PixelsBuffer content = new PixelsBuffer( COS_THETA_SUBDIVS_COUNT * ROUGHNESS_SUBDIVS_COUNT * 4 ) ) { // // using ( FileStream S = MSBRDFFileName.OpenRead() ) // // using ( BinaryReader R = new BinaryReader( S ) ) // // using ( BinaryWriter W = content.OpenStreamWrite() ) { // // for ( uint Y=0; Y < ROUGHNESS_SUBDIVS_COUNT; Y++ ) { // // for ( uint X=0; X < COS_THETA_SUBDIVS_COUNT; X++ ) { // // float V = R.ReadSingle(); // // m_GGX_E[X,Y] = V; // // W.Write( V ); // // } // // } // // } // // // // m_tex_IrradianceComplement = new Texture2D( m_device, COS_THETA_SUBDIVS_COUNT, ROUGHNESS_SUBDIVS_COUNT, 1, 1, ImageUtility.PIXEL_FORMAT.R32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, false, new PixelsBuffer[] { content } ); // // } // // // // // Build average irradiance texture // // using ( PixelsBuffer content = new PixelsBuffer( ROUGHNESS_SUBDIVS_COUNT * 4 ) ) { // // using ( FileStream S = MSBRDFFileName2.OpenRead() ) // // using ( BinaryReader R = new BinaryReader( S ) ) // // using ( BinaryWriter W = content.OpenStreamWrite() ) { // // for ( uint X=0; X < ROUGHNESS_SUBDIVS_COUNT; X++ ) { // // float V = R.ReadSingle(); // // m_GGX_Eavg[X] = V; // // W.Write( V ); // // } // // } // // // // m_tex_IrradianceAverage = new Texture2D( m_device, ROUGHNESS_SUBDIVS_COUNT, 1, 1, 1, ImageUtility.PIXEL_FORMAT.R32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, false, new PixelsBuffer[] { content } ); // // } // // // ////////////////////////////////////////////////////////////////////////// // // Check single-scattering and multiple-scattering BRDFs are actual complements // // // /* // float3[,] integralChecks = new float3[COS_THETA_SUBDIVS_COUNT,ROUGHNESS_SUBDIVS_COUNT]; // for ( uint Y=0; Y < ROUGHNESS_SUBDIVS_COUNT; Y++ ) { // float m = (float) Y / (ROUGHNESS_SUBDIVS_COUNT-1); // float m2 = Math.Max( 0.01f, m*m ); // // float Eavg = SampleEavg( m ); // // for ( uint X=0; X < COS_THETA_SUBDIVS_COUNT; X++ ) { // float cosThetaO = (float) X / (COS_THETA_SUBDIVS_COUNT-1); // float sinThetaO = Mathf.Sqrt( 1 - cosThetaO*cosThetaO ); // // float NdotV = cosThetaO; // // float Eo = SampleE( cosThetaO, m ); // // const uint CHECK_THETA_SUBDIVS_COUNT = 128; // const uint CHECK_PHI_SUBDIVS_COUNT = 2*128; // // const float dPhi = Mathf.TWOPI / CHECK_PHI_SUBDIVS_COUNT; // const float dTheta = Mathf.HALFPI / CHECK_THETA_SUBDIVS_COUNT; // // float integralSS = 0.0f; // float integralMS = 0.0f; // for ( uint THETA=0; THETA < CHECK_THETA_SUBDIVS_COUNT; THETA++ ) { // // // Use regular sampling // float thetaI = Mathf.HALFPI * (0.5f+THETA) / CHECK_THETA_SUBDIVS_COUNT; // float cosThetaI = Mathf.Cos( thetaI ); // float sinThetaI = Mathf.Sin( thetaI ); // // // // Use cosine-weighted sampling // // float sqCosThetaI = (0.5f+THETA) / CHECK_THETA_SUBDIVS_COUNT; // // float cosThetaI = Mathf.Sqrt( sqCosThetaI ); // // float sinThetaI = Mathf.Sqrt( 1 - sqCosThetaI ); // // float NdotL = cosThetaI; // // for ( uint PHI=0; PHI < CHECK_PHI_SUBDIVS_COUNT; PHI++ ) { // float phi = Mathf.TWOPI * PHI / CHECK_PHI_SUBDIVS_COUNT; // // ////////////////////////////////////////////////////////////////////////// // // Single-scattering part // // // Compute cos(theta_h) = Omega_h.N where Omega_h = (Omega_i + Omega_o) / ||Omega_i + Omega_o|| is the half vector and N the surface normal // float cosThetaH = (cosThetaI + cosThetaO) / Mathf.Sqrt( 2 * (1 + cosThetaO * cosThetaI + sinThetaO * sinThetaI * Mathf.Sin( phi )) ); // // float3 omega_i = new float3( sinThetaI * Mathf.Cos( phi ), sinThetaI * Mathf.Sin( phi ), cosThetaI ); // // float3 omega_o = new float3( sinThetaO, 0, cosThetaO ); // // float3 omega_h = (omega_i + omega_o).Normalized; // // float cosThetaH = omega_h.z; // // // Compute GGX NDF // float den = 1 - cosThetaH*cosThetaH * (1 - m2); // float NDF = m2 / (Mathf.PI * den*den); // // // Compute Smith shadowing/masking // float Smith_i_den = NdotL + Mathf.Sqrt( m2 + (1-m2) * NdotL*NdotL ); // float Smith_o_den = NdotV + Mathf.Sqrt( m2 + (1-m2) * NdotV*NdotV ); // // // Full BRDF is thus... // float GGX = NDF / (Smith_i_den * Smith_o_den); // // integralSS += GGX * cosThetaI * sinThetaI; // // integralSS += GGX; // // ////////////////////////////////////////////////////////////////////////// // // Multiple-scattering part // float Ei = SampleE( cosThetaI, m ); // // float GGX_ms = Eo * Ei / Eavg; // // integralMS += GGX_ms * cosThetaI * sinThetaI; // } // } // // // Finalize // integralSS *= dTheta * dPhi; // integralMS *= dTheta * dPhi; // // integralChecks[X,Y] = new float3( integralSS, integralMS, integralSS + integralMS ); // } // } // //*/ // ////////////////////////////////////////////////////////////////////////// // // // // verify BRDF + BRDFms integration = 1 // //cube map + integration // } // // float SampleE( float _cosTheta, float _roughness ) { // _cosTheta *= COS_THETA_SUBDIVS_COUNT; // _roughness *= ROUGHNESS_SUBDIVS_COUNT; // // float X = Mathf.Floor( _cosTheta ); // float x = _cosTheta - X; // uint X0 = Mathf.Min( COS_THETA_SUBDIVS_COUNT-1, (uint) X ); // uint X1 = Mathf.Min( COS_THETA_SUBDIVS_COUNT-1, X0+1 ); // // float Y = Mathf.Floor( _roughness ); // float y = _roughness - Y; // uint Y0 = Mathf.Min( ROUGHNESS_SUBDIVS_COUNT-1, (uint) Y ); // uint Y1 = Mathf.Min( ROUGHNESS_SUBDIVS_COUNT-1, Y0+1 ); // // float V00 = m_GGX_E[X0,Y0]; // float V10 = m_GGX_E[X1,Y0]; // float V01 = m_GGX_E[X0,Y1]; // float V11 = m_GGX_E[X1,Y1]; // // float V0 = (1.0f - x) * V00 + x * V10; // float V1 = (1.0f - x) * V01 + x * V11; // float V = (1.0f - y) * V0 + y * V1; // return V; // } // float SampleEavg( float _roughness ) { // _roughness *= ROUGHNESS_SUBDIVS_COUNT; // float X = Mathf.Floor( _roughness ); // float x = _roughness - X; // uint X0 = Mathf.Min( ROUGHNESS_SUBDIVS_COUNT-1, (uint) X ); // uint X1 = Mathf.Min( ROUGHNESS_SUBDIVS_COUNT-1, X0+1 ); // // float V0 = m_GGX_Eavg[X0]; // float V1 = m_GGX_Eavg[X1]; // float V = (1.0f - x) * V0 + x * V1; // return V; // } void LoadMSBRDF(int _size, FileInfo _irradianceTableName, FileInfo _whiteFurnaceTableName, out Texture2D _irradianceTexture, out Texture2D _whiteFurnaceTexture) { // Read irradiance table float[,] irradianceTable = new float[_size, _size]; PixelsBuffer contentIrradiance = new PixelsBuffer((uint)(_size * _size * 4)); using (FileStream S = _irradianceTableName.OpenRead()) using (BinaryReader R = new BinaryReader(S)) { using (BinaryWriter W = contentIrradiance.OpenStreamWrite()) { for (int Y = 0; Y < _size; Y++) { for (int X = 0; X < _size; X++) { float V = R.ReadSingle(); irradianceTable[X, Y] = V; W.Write(V); } } } } // Read white furnace table float[] whiteFurnaceTable = new float[_size]; PixelsBuffer contentWhiteFurnace = new PixelsBuffer((uint)(_size * 4)); using (FileStream S = _whiteFurnaceTableName.OpenRead()) using (BinaryReader R = new BinaryReader(S)) { using (BinaryWriter W = contentWhiteFurnace.OpenStreamWrite()) { for (int Y = 0; Y < _size; Y++) { float V = R.ReadSingle(); whiteFurnaceTable[Y] = V; W.Write(V); } } } // Create textures _irradianceTexture = new Texture2D(m_device, (uint)_size, (uint)_size, 1, 1, ImageUtility.PIXEL_FORMAT.R32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, new PixelsBuffer[] { contentIrradiance }); _whiteFurnaceTexture = new Texture2D(m_device, (uint)_size, 1, 1, 1, ImageUtility.PIXEL_FORMAT.R32F, ImageUtility.COMPONENT_FORMAT.AUTO, false, true, new PixelsBuffer[] { contentWhiteFurnace }); }
private void btnInverseDrawStar_Click(object sender, EventArgs e) { //intentionally make the stride negative so that //the coordinate system is flipped from top-down to bottom-up int stride = -height; //create buffer PixelsBuffer buffer = new PixelsBuffer(width, height, stride); //render DrawStar(buffer, Colors.Blue, Colors.White); //show to screen DisplayBuffer(buffer); #region Description string msg = "Similar to Draw Star example, except that the y-axis is inversed"; txtDescription.Text = msg; #endregion }
private void Build3DDensityField() { PixelsBuffer DensityField = new PixelsBuffer( DENSITY_FIELD_SIZE*DENSITY_FIELD_SIZE*DENSITY_FIELD_HEIGHT ); byte D; float3 P; float3 C = new float3( 0.5f, 0.5f, 0.5f ); using ( System.IO.BinaryWriter W = DensityField.OpenStreamWrite() ) for ( int X=0; X < DENSITY_FIELD_SIZE; X++ ) { P.x = (0.5f+X) / DENSITY_FIELD_SIZE; for ( int Y=0; Y < DENSITY_FIELD_HEIGHT; Y++ ) { P.y = (0.5f+Y) / DENSITY_FIELD_HEIGHT; for ( int Z=0; Z < DENSITY_FIELD_SIZE; Z++ ) { P.z = (0.5f+Z) / DENSITY_FIELD_SIZE; // D = 0; // Empty for now: photons should go straight through! D = (byte) ((P - C).LengthSquared < 0.125f ? 255 : 0); W.Write( D ); } } } Reg( m_Tex_DensityField = new Texture3D( m_Device, DENSITY_FIELD_SIZE, DENSITY_FIELD_HEIGHT, DENSITY_FIELD_SIZE, 1, PIXEL_FORMAT.R8_UNORM, false, false, new PixelsBuffer[] { DensityField } ) ); DensityField.Dispose(); }
public Texture2D Image2Texture( int _Width, int _Height, PixelsBuffer _Content ) { return new Texture2D( m_Device, _Width, _Height, 1, 1, PIXEL_FORMAT.RGBA8_UNORM_sRGB, false, false, new PixelsBuffer[] { _Content } ); }
void BuildNoiseTextures() { PixelsBuffer Content = new PixelsBuffer( NOISE_SIZE*NOISE_SIZE*NOISE_SIZE*4 ); PixelsBuffer Content4D = new PixelsBuffer( NOISE_SIZE*NOISE_SIZE*NOISE_SIZE*16 ); WMath.SimpleRNG.SetSeed( 521288629, 362436069 ); float4 V = float4.Zero; using ( BinaryWriter W = Content.OpenStreamWrite() ) { using ( BinaryWriter W2 = Content4D.OpenStreamWrite() ) { for ( int Z=0; Z < NOISE_SIZE; Z++ ) for ( int Y=0; Y < NOISE_SIZE; Y++ ) for ( int X=0; X < NOISE_SIZE; X++ ) { V.Set( (float) WMath.SimpleRNG.GetUniform(), (float) WMath.SimpleRNG.GetUniform(), (float) WMath.SimpleRNG.GetUniform(), (float) WMath.SimpleRNG.GetUniform() ); W.Write( V.x ); W2.Write( V.x ); W2.Write( V.y ); W2.Write( V.z ); W2.Write( V.w ); } } } m_Tex_Noise = new Texture3D( m_Device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, PIXEL_FORMAT.R8_UNORM, false, false, new PixelsBuffer[] { Content } ); m_Tex_Noise4D = new Texture3D( m_Device, NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, 1, PIXEL_FORMAT.RGBA8_UNORM, false, false, new PixelsBuffer[] { Content4D } ); }
private void LoadResults( System.IO.FileInfo _FileName ) { try { groupBoxOptions.Enabled = false; // Dispose of existing resources if ( m_TextureTargets[0][0] != null ) { m_TextureTargets[0][0].Dispose(); m_TextureTargets[0][1].Dispose(); m_TextureTargets[1][0].Dispose(); m_TextureTargets[1][1].Dispose(); m_TextureTargets[2][0].Dispose(); m_TextureTargets[2][1].Dispose(); m_TextureTargetCombined.Dispose(); } m_TextureTargets[0][0] = null; m_TextureTargets[0][1] = null; m_TextureTargets[1][0] = null; m_TextureTargets[1][1] = null; m_TextureTargets[2][0] = null; m_TextureTargets[2][1] = null; m_TextureTargetCombined = null; if ( m_imageResults[0] != null ) m_imageResults[0].Dispose(); if ( m_imageResults[1] != null ) m_imageResults[1].Dispose(); if ( m_imageResults[2] != null ) m_imageResults[2].Dispose(); if ( m_imageResultCombined != null ) m_imageResultCombined.Dispose(); // m_imageResults[0] = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.R8, m_sRGBProfile ); // m_imageResults[1] = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.R8, m_sRGBProfile ); // m_imageResults[2] = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.R8, m_sRGBProfile ); // m_imageResultCombined = new ImageUtility.ImageFile( W, H, ImageUtility.ImageFile.PIXEL_FORMAT.RGBA8, m_sRGBProfile ); m_imageResults[0] = new ImageUtility.ImageFile(); m_imageResults[1] = new ImageUtility.ImageFile(); m_imageResults[2] = new ImageUtility.ImageFile(); m_imageResultCombined = new ImageUtility.ImageFile(); // Load the result images assuming it's in sRGB space string[] FileNames = new string[4] { System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency0.png" ), System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency1.png" ), System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency2.png" ), System.IO.Path.Combine( System.IO.Path.GetDirectoryName( _FileName.FullName ), System.IO.Path.GetFileNameWithoutExtension( _FileName.FullName ) + "_translucency.png" ), }; ImageUtility.ImageFile[] images = new ImageUtility.ImageFile[] { m_imageResults[0], m_imageResults[1], m_imageResults[2], m_imageResultCombined }; Texture2D[] Results = new Texture2D[] { m_TextureTargets[0][0], m_TextureTargets[1][0], m_TextureTargets[2][0], m_TextureTargetCombined, }; ImagePanel[] Panels = new ImagePanel[] { imagePanelResult0, imagePanelResult1, imagePanelResult2, imagePanelResult3, }; for ( int i=0; i < 4; i++ ) { ImageUtility.ImageFile B = images[i]; B.Load( new System.IO.FileInfo( FileNames[i] ) ); Panels[i].Image = B; // Build the texture assuming sRGB sources float4[] scanline = new float4[B.Width]; float4 linearRGB = float4.Zero; PixelsBuffer sourceMap = new PixelsBuffer( B.Width*B.Height*16 ); using ( System.IO.BinaryWriter Wr = sourceMap.OpenStreamWrite() ) for ( uint Y=0; Y < B.Height; Y++ ) { B.ReadScanline( Y, scanline ); for ( uint X=0; X < B.Width; X++ ) { m_sRGBProfile.GammaRGB2LinearRGB( scanline[X], ref linearRGB ); Wr.Write( linearRGB.x ); Wr.Write( linearRGB.y ); Wr.Write( linearRGB.z ); Wr.Write( linearRGB.w ); } } Results[i] = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, true, new PixelsBuffer[] { sourceMap } ); } m_TextureTargets[0][0] = Results[0]; m_TextureTargets[0][1] = Results[0]; m_TextureTargets[1][0] = Results[1]; m_TextureTargets[1][1] = Results[1]; m_TextureTargets[2][0] = Results[2]; m_TextureTargets[2][1] = Results[2]; m_TextureTargetCombined = Results[3]; } catch ( Exception _e ) { MessageBox( "An error occurred while opening the result maps \"" + _FileName.FullName + "\":\n\n", _e ); } }
/// <summary> /// Builds a heightfield whose heights are distributed according to the following probability (a.k.a. the normal distribution with sigma=1 and µ=0): /// p(height) = exp( -0.5*height^2 ) / sqrt(2PI) /// /// From "2015 Heitz - Generating Procedural Beckmann Surfaces" /// </summary> /// <param name="_roughness"></param> /// <remarks>Only isotropic roughness is supported</remarks> public void BuildBeckmannSurfaceTexture( float _roughness ) { m_internalChange = true; // Shouldn't happen but modifying the slider value may trigger a call to this function again, this flag prevents it // Mirror current roughness floatTrackbarControlBeckmannRoughness.Value = _roughness; // Precompute stuff that resemble a lot to the Box-Muller algorithm to generate normal distribution random values WMath.SimpleRNG.SetSeed( 521288629, 362436069 ); for ( int i=0; i < m_SB_Beckmann.m.Length; i++ ) { double U0 = WMath.SimpleRNG.GetUniform(); double U1 = WMath.SimpleRNG.GetUniform(); double U2 = WMath.SimpleRNG.GetUniform(); m_SB_Beckmann.m[i].m_phase = (float) (2.0 * Math.PI * U0); // Phase double theta = 2.0 * Math.PI * U1; double radius = Math.Sqrt( -Math.Log( U2 ) ); m_SB_Beckmann.m[i].m_frequencyX = (float) (radius * Math.Cos( theta ) * _roughness); // Frequency in X direction m_SB_Beckmann.m[i].m_frequencyY = (float) (radius * Math.Sin( theta ) * _roughness); // Frequency in Y direction } m_SB_Beckmann.Write(); m_SB_Beckmann.SetInput( 0 ); #if true if ( m_Tex_Heightfield == null ) m_Tex_Heightfield = new Texture2D( m_Device, HEIGHTFIELD_SIZE, HEIGHTFIELD_SIZE, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, true, null ); // Run the CS if ( m_Shader_ComputeBeckmannSurface.Use() ) { m_Tex_Heightfield.SetCSUAV( 0 ); float size = floatTrackbarControlBeckmannSizeFactor.Value * HEIGHTFIELD_SIZE; // m_CB_ComputeBeckmann.m._Position_Size.Set( -128.0f, -128.0f, 256.0f, 256.0f ); m_CB_ComputeBeckmann.m._Position_Size.Set( -0.5f * size, -0.5f * size, size, size ); m_CB_ComputeBeckmann.m._HeightFieldResolution = HEIGHTFIELD_SIZE; m_CB_ComputeBeckmann.m._SamplesCount = (uint) m_SB_Beckmann.m.Length; m_CB_ComputeBeckmann.UpdateData(); m_Shader_ComputeBeckmannSurface.Dispatch( HEIGHTFIELD_SIZE >> 4, HEIGHTFIELD_SIZE >> 4, 1 ); m_Tex_Heightfield.RemoveFromLastAssignedSlotUAV(); } #else // CPU version PixelsBuffer Content = new PixelsBuffer( HEIGHTFIELD_SIZE*HEIGHTFIELD_SIZE*System.Runtime.InteropServices.Marshal.SizeOf(typeof(float)) ); double scale = Math.Sqrt( 2.0 / N ); // Generate heights float range = 128.0f; float2 pos; float height; float minHeight = float.MaxValue, maxHeight = -float.MaxValue; double accum; using ( BinaryWriter W = Content.OpenStreamWrite() ) { for ( int Y=0; Y < HEIGHTFIELD_SIZE; Y++ ) { pos.y = range * (2.0f * Y / (HEIGHTFIELD_SIZE-1) - 1.0f); for ( int X=0; X < HEIGHTFIELD_SIZE; X++ ) { pos.x = range * (2.0f * X / (HEIGHTFIELD_SIZE-1) - 1.0f); // height = (float) WMath.SimpleRNG.GetNormal(); // height = (float) GenerateNormalDistributionHeight(); accum = 0.0; for ( int i=0; i < N; i++ ) { accum += Math.Cos( m_phi[i] + pos.x * m_fx[i] + pos.y * m_fy[i] ); } height = (float) (scale * accum); minHeight = Math.Min( minHeight, height ); maxHeight = Math.Max( maxHeight, height ); W.Write( height ); } } } Content.CloseStream(); m_Tex_Heightfield = new Texture2D( m_Device, HEIGHTFIELD_SIZE, HEIGHTFIELD_SIZE, 1, 1, PIXEL_FORMAT.R32_FLOAT, false, false, new PixelsBuffer[] { Content } ); #endif m_internalChange = false; }
void LoadProbePixels( FileInfo _FileName ) { if ( m_Tex_CubeMap != null ) { m_Tex_CubeMap.Dispose(); m_Tex_CubeMap = null; } if ( m_SB_Samples != null ) { m_SB_Samples.Dispose(); m_SB_Samples = null; } if ( m_SB_EmissiveSurfaces != null ) { m_SB_EmissiveSurfaces.Dispose(); m_SB_EmissiveSurfaces = null; } using ( FileStream S = _FileName.OpenRead() ) using ( BinaryReader R = new BinaryReader( S ) ) { ////////////////////////////////////////////////////////////////// // Read pixels Pixel[][,] CubeMapFaces = new Pixel[6][,]; int CubeMapSize = R.ReadInt32(); for ( int CubeMapFaceIndex=0; CubeMapFaceIndex < 6; CubeMapFaceIndex++ ) { Pixel[,] Face = new Pixel[CubeMapSize,CubeMapSize]; CubeMapFaces[CubeMapFaceIndex] = Face; for ( int Y=0; Y < CubeMapSize; Y++ ) for ( int X=0; X < CubeMapSize; X++ ) { Face[X,Y].ParentSampleIndex = R.ReadUInt32(); Face[X,Y].UsedForSampling = R.ReadBoolean(); Face[X,Y].Position.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].Normal.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].Albedo.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].F0.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].StaticLitColor.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].SmoothedStaticLitColor.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); Face[X,Y].FaceIndex = R.ReadUInt32(); Face[X,Y].EmissiveMatID = R.ReadUInt32(); Face[X,Y].NeighborProbeID = R.ReadUInt32(); Face[X,Y].NeighborProbeDistance = R.ReadSingle(); Face[X,Y].VoronoiProbeID = R.ReadUInt32(); Face[X,Y].Importance = R.ReadDouble(); Face[X,Y].Distance = R.ReadSingle(); Face[X,Y].SmoothedDistance = R.ReadSingle(); Face[X,Y].Infinity = R.ReadByte() != 0; Face[X,Y].SmoothedInfinity = R.ReadSingle(); } } List<PixelsBuffer> Content = new List<PixelsBuffer>(); float4 Value = new float4(); for ( int CubeIndex=0; CubeIndex < 8; CubeIndex++ ) { for ( int CubeMapFaceIndex=0; CubeMapFaceIndex < 6; CubeMapFaceIndex++ ) { PixelsBuffer Buff = new PixelsBuffer( CubeMapSize*CubeMapSize * 16 ); Content.Add( Buff ); using ( BinaryWriter W = Buff.OpenStreamWrite() ) { for ( int Y=0; Y < CubeMapSize; Y++ ) for ( int X=0; X < CubeMapSize; X++ ) { Pixel P = CubeMapFaces[CubeMapFaceIndex][X,Y]; switch ( CubeIndex ) { case 0: Value.Set( P.Position, P.Distance ); break; case 1: Value.Set( P.Normal, P.SmoothedDistance ); break; case 2: Value.Set( P.Albedo, P.SmoothedInfinity ); break; case 3: Value.Set( P.StaticLitColor, (float) P.ParentSampleIndex ); break; case 4: Value.Set( P.SmoothedStaticLitColor, (float) P.Importance ); break; case 5: Value.Set( P.UsedForSampling ? 1 : 0, P.Infinity ? 1 : 0, (float) P.FaceIndex, (float) P.VoronoiProbeID ); break; case 6: Value.Set( P.F0, (float) P.NeighborProbeID ); break; case 7: Value.Set( P.NeighborProbeDistance, 0, 0, 0 ); break; } W.Write( Value.x ); W.Write( Value.y ); W.Write( Value.z ); W.Write( Value.w ); } } } } m_Tex_CubeMap = new Texture2D( m_Device, CubeMapSize, CubeMapSize, -6*8, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, Content.ToArray() ); ////////////////////////////////////////////////////////////////// // Read samples int SamplesCount = (int) R.ReadUInt32(); m_SB_Samples = new StructuredBuffer<SB_Sample>( m_Device, SamplesCount, true ); for ( int SampleIndex=0; SampleIndex < SamplesCount; SampleIndex++ ) { m_SB_Samples.m[SampleIndex].ID = (uint) SampleIndex; m_SB_Samples.m[SampleIndex].Position.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].Normal.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].Albedo.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].F0.Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); m_SB_Samples.m[SampleIndex].PixelsCount = R.ReadUInt32(); m_SB_Samples.m[SampleIndex].SHFactor = R.ReadSingle(); m_SB_Samples.m[SampleIndex].SH0.Set( (float) R.ReadDouble(), (float) R.ReadDouble(), (float) R.ReadDouble() ); m_SB_Samples.m[SampleIndex].SH1.Set( (float) R.ReadDouble(), (float) R.ReadDouble(), (float) R.ReadDouble() ); m_SB_Samples.m[SampleIndex].SH2.Set( (float) R.ReadDouble(), (float) R.ReadDouble(), (float) R.ReadDouble() ); } m_SB_Samples.Write(); } }
public Texture2D Image2Texture( uint _Width, uint _Height, byte[] _Content ) { using ( PixelsBuffer Buff = new PixelsBuffer( (uint) _Content.Length ) ) { using ( System.IO.BinaryWriter W = Buff.OpenStreamWrite() ) W.Write( _Content ); return Image2Texture( _Width, _Height, PIXEL_FORMAT.RGBA8_UNORM_sRGB, Buff ); } }
private void LoadHeightMap( System.IO.FileInfo _FileName ) { try { tabControlGenerators.Enabled = false; // Dispose of existing resources if ( m_imageSourceHeightMap != null ) m_imageSourceHeightMap.Dispose(); m_imageSourceHeightMap = null; if ( m_textureTarget_CPU != null ) m_textureTarget_CPU.Dispose(); m_textureTarget_CPU = null; if ( m_textureTarget0 != null ) m_textureTarget0.Dispose(); m_textureTarget0 = null; if ( m_textureTarget1 != null ) m_textureTarget1.Dispose(); m_textureTarget1 = null; if ( m_textureSourceHeightMap != null ) m_textureSourceHeightMap.Dispose(); m_textureSourceHeightMap = null; // Load the source image m_SourceFileName = _FileName; m_imageSourceHeightMap = new ImageUtility.ImageFile( _FileName ); outputPanelInputHeightMap.Image = m_imageSourceHeightMap; W = m_imageSourceHeightMap.Width; H = m_imageSourceHeightMap.Height; // Build the source texture assuming the image is in linear space float4[] scanline = new float4[W]; PixelsBuffer SourceHeightMap = new PixelsBuffer( W*H*4 ); using ( System.IO.BinaryWriter Wr = SourceHeightMap.OpenStreamWrite() ) for ( uint Y=0; Y < H; Y++ ) { m_imageSourceHeightMap.ReadScanline( Y, scanline ); for ( int X=0; X < W; X++ ) Wr.Write( scanline[X].x ); } m_textureSourceHeightMap = new Texture2D( m_device, W, H, 1, 1, PIXEL_FORMAT.R32_FLOAT, false, false, new PixelsBuffer[] { SourceHeightMap } ); // Build the target UAV & staging texture for readback m_textureTarget0 = new Texture2D( m_device, W, H, 1, 1, PIXEL_FORMAT.R32_FLOAT, false, true, null ); m_textureTarget1 = new Texture2D( m_device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, true, null ); m_textureTarget_CPU = new Texture2D( m_device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, true, false, null ); tabControlGenerators.Enabled = true; buttonGenerate.Focus(); } catch ( Exception _e ) { MessageBox( "An error occurred while opening the image:\n\n", _e ); } }
public Texture3D Image2Texture3D( uint _Width, uint _Height, uint _Depth, PIXEL_FORMAT _Format, PixelsBuffer[] _SlicesContent ) { return new Texture3D( m_Device, _Width, _Height, _Depth, 1, _Format, false, false, _SlicesContent ); }
public Texture2D Image2Texture( uint _Width, uint _Height, PIXEL_FORMAT _Format, PixelsBuffer _Content ) { return Image2Texture( _Width, _Height, _Format, new PixelsBuffer[] { _Content } ); }
public Texture2D Image2Texture( uint _Width, uint _Height, PIXEL_FORMAT _Format, PixelsBuffer[] _MipsContent ) { return new Texture2D( m_Device, _Width, _Height, 1, (uint) _MipsContent.Length, _Format, false, false, _MipsContent ); }
/// <summary> /// Builds the surface texture from an actual image file /// </summary> /// <param name="_textureFileName"></param> /// <param name="_pixelSize">Size of a pixel, assuming the maximum height is 1</param> public unsafe void BuildSurfaceFromTexture( string _textureFileName, float _pixelSize ) { if ( m_Tex_Heightfield != null ) m_Tex_Heightfield.Dispose(); // We will create a new one so dispose of the old one... // Read the bitmap int W, H; float4[,] Content = null; using ( Bitmap BM = Bitmap.FromFile( _textureFileName ) as Bitmap ) { W = BM.Width; H = BM.Height; Content = new float4[W,H]; BitmapData LockedBitmap = BM.LockBits( new Rectangle( 0, 0, W, H ), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb ); byte R, G, B, A; for ( int Y=0; Y < H; Y++ ) { byte* pScanline = (byte*) LockedBitmap.Scan0.ToPointer() + Y*LockedBitmap.Stride; for ( int X=0; X < W; X++ ) { // Read in shitty order B = *pScanline++; G = *pScanline++; R = *pScanline++; A = *pScanline++; // Use this if you really need RGBA data // Content[X,Y].Set( R / 255.0f, G / 255.0f, B / 255.0f, A / 255.0f ); // But assuming it's a height field, we only store one component into alpha Content[X,Y].Set( 0, 0, 0, R / 255.0f ); // Use Red as height } } BM.UnlockBits( LockedBitmap ); } // Build normal (shitty version) float Hx0, Hx1, Hy0, Hy1; float3 dNx = new float3( 2.0f * _pixelSize, 0, 0 ); float3 dNy = new float3( 0, 2.0f * _pixelSize, 0 ); float3 N; for ( int Y=0; Y < H; Y++ ) { int pY = (Y+H-1) % H; int nY = (Y+1) % H; for ( int X=0; X < W; X++ ) { int pX = (X+W-1) % W; int nX = (X+1) % W; Hx0 = Content[pX,Y].w; Hx1 = Content[nX,Y].w; Hy0 = Content[X,pY].w; Hy1 = Content[X,nY].w; dNx.z = Hx1 - Hx0; dNy.z = Hy0 - Hy1; // Assuming +Y is upward N = dNx.Cross( dNy ); N = N.Normalized; Content[X,Y].x = N.x; Content[X,Y].y = N.y; Content[X,Y].z = N.z; } } // Build the texture from the array PixelsBuffer Buf = new PixelsBuffer( W*H*16 ); using ( BinaryWriter Writer = Buf.OpenStreamWrite() ) for ( int Y=0; Y < H; Y++ ) for ( int X=0; X < W; X++ ) { float4 pixel = Content[X,Y]; Writer.Write( pixel.x ); Writer.Write( pixel.y ); Writer.Write( pixel.z ); Writer.Write( pixel.w ); } Buf.CloseStream(); m_Tex_Heightfield = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, new PixelsBuffer[] { Buf } ); }
public Texture3D Pipu2Texture( System.IO.FileInfo _FileName ) { using ( System.IO.FileStream S = _FileName.OpenRead() ) using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) { int SlicesCount = R.ReadInt32(); int W = R.ReadInt32(); int H = R.ReadInt32(); PixelsBuffer Slices = new PixelsBuffer( (uint) (4 * W * H * SlicesCount * 4) ); using ( System.IO.BinaryWriter Wr = Slices.OpenStreamWrite() ) { for ( int SliceIndex=0; SliceIndex < SlicesCount; SliceIndex++ ) { float4 C = new float4(); for ( int Y=0; Y < H; Y++ ) { for ( int X=0; X < W; X++ ) { C.x = R.ReadSingle(); C.y = R.ReadSingle(); C.z = R.ReadSingle(); C.w = R.ReadSingle(); Wr.Write( C.x ); Wr.Write( C.y ); Wr.Write( C.z ); Wr.Write( C.w ); } } } } return Image2Texture3D( (uint) W, (uint) H, (uint) SlicesCount, PIXEL_FORMAT.RGBA32_FLOAT, new PixelsBuffer[] { Slices } ); } }
public Texture2D Pipi2Texture( System.IO.FileInfo _FileName ) { using ( System.IO.FileStream S = _FileName.OpenRead() ) using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) { int MipLevels = R.ReadInt32(); PixelsBuffer[] Mips = new PixelsBuffer[MipLevels]; int ImageWidth = 0, ImageHeight = 0; for ( int MipLevel=0; MipLevel < MipLevels; MipLevel++ ) { int W, H; W = R.ReadInt32(); H = R.ReadInt32(); if ( MipLevel == 0 ) { ImageWidth = W; ImageHeight = H; } PixelsBuffer Buff = new PixelsBuffer( (uint) (4 * W * H * 4) ); Mips[MipLevel] = Buff; using ( System.IO.BinaryWriter Wr = Buff.OpenStreamWrite() ) { float4 C = new float4(); for ( int Y=0; Y < H; Y++ ) { for ( int X=0; X < W; X++ ) { C.x = R.ReadSingle(); C.y = R.ReadSingle(); C.z = R.ReadSingle(); C.w = R.ReadSingle(); Wr.Write( C.x ); Wr.Write( C.y ); Wr.Write( C.z ); Wr.Write( C.w ); } } } } return Image2Texture( (uint) ImageWidth, (uint) ImageHeight, PIXEL_FORMAT.RGBA32_FLOAT, Mips ); } }
private void LoadThicknessMap( System.IO.FileInfo _FileName ) { try { groupBoxOptions.Enabled = false; // Dispose of existing resources if ( m_ImageSourceThickness != null ) m_ImageSourceThickness.Dispose(); m_ImageSourceThickness = null; if ( m_TextureSourceThickness != null ) m_TextureSourceThickness.Dispose(); m_TextureSourceThickness = null; if ( m_TextureSourceVisibility != null ) m_TextureSourceVisibility.Dispose(); m_TextureSourceVisibility = null; if ( m_TextureTarget_CPU != null ) { m_TextureTarget_CPU.Dispose(); } m_TextureTarget_CPU = null; if ( m_TextureFilteredThickness != null ) m_TextureFilteredThickness.Dispose(); m_TextureFilteredThickness = null; if ( m_TextureTargets[0][0] != null ) { m_TextureTargets[0][0].Dispose(); m_TextureTargets[0][1].Dispose(); m_TextureTargets[1][0].Dispose(); m_TextureTargets[1][1].Dispose(); m_TextureTargets[2][0].Dispose(); m_TextureTargets[2][1].Dispose(); } m_TextureTargets[0][0] = null; m_TextureTargets[0][1] = null; m_TextureTargets[1][0] = null; m_TextureTargets[1][1] = null; m_TextureTargets[2][0] = null; m_TextureTargets[2][1] = null; if ( m_TextureTargetCombined != null ) m_TextureTargetCombined.Dispose(); m_TextureTargetCombined = null; // Load the source image m_SourceFileName = _FileName; m_ImageSourceThickness = new ImageUtility.ImageFile( _FileName ); imagePanelThicknessMap.Image = m_ImageSourceThickness; W = m_ImageSourceThickness.Width; H = m_ImageSourceThickness.Height; // Build the source texture assuming the image is in linear space float4[] scanline = new float4[W]; PixelsBuffer sourceHeightMap = new PixelsBuffer( W*H*4 ); using ( System.IO.BinaryWriter Wr = sourceHeightMap.OpenStreamWrite() ) for ( uint Y=0; Y < H; Y++ ) { m_ImageSourceThickness.ReadScanline( Y, scanline ); for ( uint X=0; X < W; X++ ) { Wr.Write( scanline[X].x ); } } m_TextureSourceThickness = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.R32_FLOAT, false, false, new PixelsBuffer[] { sourceHeightMap } ); // Build the 3D visibility texture m_TextureSourceVisibility = new Texture3D( m_Device, W, H, VISIBILITY_SLICES, 1, PIXEL_FORMAT.R16_FLOAT, false, true, null ); // Build the target UAV & staging texture for readback m_TextureFilteredThickness = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.R32_FLOAT, false, true, null ); for ( int i=0; i < 3; i++ ) { m_TextureTargets[i][0] = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, true, null ); m_TextureTargets[i][1] = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, true, null ); } m_TextureTargetCombined = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, true, null ); m_TextureTarget_CPU = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, true, false, null ); groupBoxOptions.Enabled = true; buttonGenerate.Focus(); } catch ( Exception _e ) { MessageBox( "An error occurred while opening the thickness map \"" + _FileName.FullName + "\":\n\n", _e ); } }
/* https://knarkowicz.wordpress.com/2014/12/27/analytical-dfg-term-for-ibl/ uint32_t ReverseBits( uint32_t v ) { v = ( ( v >> 1 ) & 0x55555555 ) | ( ( v & 0x55555555 ) << 1 ); v = ( ( v >> 2 ) & 0x33333333 ) | ( ( v & 0x33333333 ) << 2 ); v = ( ( v >> 4 ) & 0x0F0F0F0F ) | ( ( v & 0x0F0F0F0F ) << 4 ); v = ( ( v >> 8 ) & 0x00FF00FF ) | ( ( v & 0x00FF00FF ) << 8 ); v = ( v >> 16 ) | ( v << 16 ); return v; } float GSmith( float roughness, float ndotv, float ndotl ) { float const m2 = roughness * roughness; float const visV = ndotv + sqrt( ndotv * ( ndotv - ndotv * m2 ) + m2 ); float const visL = ndotl + sqrt( ndotl * ( ndotl - ndotl * m2 ) + m2 ); return 1.0f / ( visV * visL ); } int main() { float const MATH_PI = 3.14159f; unsigned const LUT_WIDTH = 128; unsigned const LUT_HEIGHT = 128; unsigned const sampleNum = 128; float lutData[ LUT_WIDTH * LUT_HEIGHT * 4 ]; for ( unsigned y = 0; y < LUT_HEIGHT; ++y ) { float const ndotv = ( y + 0.5f ) / LUT_WIDTH; for ( unsigned x = 0; x < LUT_WIDTH; ++x ) { float const gloss = ( x + 0.5f ) / LUT_HEIGHT; float const roughness = powf( 1.0f - gloss, 4.0f ); float const vx = sqrtf( 1.0f - ndotv * ndotv ); float const vy = 0.0f; float const vz = ndotv; float scale = 0.0f; float bias = 0.0f; for ( unsigned i = 0; i < sampleNum; ++i ) { float const e1 = (float) i / sampleNum; float const e2 = (float) ( (double) ReverseBits( i ) / (double) 0x100000000LL ); float const phi = 2.0f * MATH_PI * e1; float const cosPhi = cosf( phi ); float const sinPhi = sinf( phi ); float const cosTheta = sqrtf( ( 1.0f - e2 ) / ( 1.0f + ( roughness * roughness - 1.0f ) * e2 ) ); float const sinTheta = sqrtf( 1.0f - cosTheta * cosTheta ); float const hx = sinTheta * cosf( phi ); float const hy = sinTheta * sinf( phi ); float const hz = cosTheta; float const vdh = vx * hx + vy * hy + vz * hz; float const lx = 2.0f * vdh * hx - vx; float const ly = 2.0f * vdh * hy - vy; float const lz = 2.0f * vdh * hz - vz; float const ndotl = std::max( lz, 0.0f ); float const ndoth = std::max( hz, 0.0f ); float const vdoth = std::max( vdh, 0.0f ); if ( ndotl > 0.0f ) { float const gsmith = GSmith( roughness, ndotv, ndotl ); float const ndotlVisPDF = ndotl * gsmith * ( 4.0f * vdoth / ndoth ); float const fc = powf( 1.0f - vdoth, 5.0f ); scale += ndotlVisPDF * ( 1.0f - fc ); bias += ndotlVisPDF * fc; } } scale /= sampleNum; bias /= sampleNum; lutData[ x * 4 + y * LUT_WIDTH * 4 + 0 ] = scale; lutData[ x * 4 + y * LUT_WIDTH * 4 + 1 ] = bias; lutData[ x * 4 + y * LUT_WIDTH * 4 + 2 ] = 0.0f; lutData[ x * 4 + y * LUT_WIDTH * 4 + 3 ] = 0.0f; } } } */ #endif Texture2D BuildBRDFTexture( System.IO.FileInfo _TableFileName, uint _TableSize ) { float2[,] Table = new float2[_TableSize,_TableSize]; float MinA = 1, MaxA = 0; float MinB = 1, MaxB = 0; using ( System.IO.FileStream S = _TableFileName.OpenRead() ) using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) for ( int Y=0; Y < _TableSize; Y++ ) for ( int X=0; X < _TableSize; X++ ) { float A = R.ReadSingle(); float B = R.ReadSingle(); Table[X,Y].x = A; Table[X,Y].y = B; MinA = Math.Min( MinA, A ); MaxA = Math.Max( MaxA, A ); MinB = Math.Min( MinB, B ); MaxB = Math.Max( MaxB, B ); } // MaxA = 1 // MaxB = 0.00014996325546887346 // MaxA = 1.0; // MaxB = 1.0; // Create the texture // PixelsBuffer Content = new PixelsBuffer( _TableSize*_TableSize*4 ); PixelsBuffer Content = new PixelsBuffer( (uint) (_TableSize*_TableSize*2*4) ); using ( System.IO.BinaryWriter W = Content.OpenStreamWrite() ) for ( int Y=0; Y < _TableSize; Y++ ) for ( int X=0; X < _TableSize; X++ ) { // W.Write( (ushort) (65535.0 * Table[X,Y].x / MaxA) ); // W.Write( (ushort) (65535.0 * Table[X,Y].y / MaxB) ); W.Write( Table[X,Y].x ); W.Write( Table[X,Y].y ); } // Texture2D Result = new Texture2D( m_Device, _TableSize, _TableSize, 1, 1, PIXEL_FORMAT.RG16_UNORM, false, false, new PixelsBuffer[] { Content } ); Texture2D Result = new Texture2D( m_Device, _TableSize, _TableSize, 1, 1, PIXEL_FORMAT.RG32_FLOAT, false, false, new PixelsBuffer[] { Content } ); return Result; }
private void LoadAlbedoMap( System.IO.FileInfo _FileName ) { try { // Dispose of existing resources if ( m_imageSourceAlbedo != null ) m_imageSourceAlbedo.Dispose(); m_imageSourceAlbedo = null; if ( m_TextureSourceAlbedo != null ) m_TextureSourceAlbedo.Dispose(); m_TextureSourceAlbedo = null; // Load the source image m_imageSourceAlbedo = new ImageUtility.ImageFile( _FileName ); imagePanelAlbedoMap.Image = m_imageSourceAlbedo; uint W = m_imageSourceAlbedo.Width; uint H = m_imageSourceAlbedo.Height; // Build the source texture assuming the image's color profile float4[] scanline = new float4[W]; float4 linearRGB = float4.Zero; ImageUtility.ColorProfile imageProfile = m_imageSourceAlbedo.ColorProfile; // ImageUtility.ColorProfile imageProfile = m_sRGBProfile; // float4[,] ContentRGB = new float4[W,H]; // m_LinearProfile.XYZ2RGB( m_imageSourceAlbedo.ContentXYZ, ContentRGB ); PixelsBuffer SourceMap = new PixelsBuffer( W*H*16 ); using ( System.IO.BinaryWriter Wr = SourceMap.OpenStreamWrite() ) for ( uint Y=0; Y < H; Y++ ) { m_imageSourceAlbedo.ReadScanline( Y, scanline ); for ( uint X=0; X < W; X++ ) { imageProfile.GammaRGB2LinearRGB( scanline[X], ref linearRGB ); Wr.Write( linearRGB.x ); Wr.Write( linearRGB.y ); Wr.Write( linearRGB.z ); Wr.Write( linearRGB.w ); } } m_TextureSourceAlbedo = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, new PixelsBuffer[] { SourceMap } ); } catch ( Exception _e ) { MessageBox( "An error occurred while opening the albedo map \"" + _FileName.FullName + "\":\n\n", _e ); } }
private void LoadNormalMap( System.IO.FileInfo _FileName ) { try { // Dispose of existing resources if ( m_imageSourceNormal != null ) m_imageSourceNormal.Dispose(); m_imageSourceNormal = null; if ( m_TextureSourceNormal != null ) m_TextureSourceNormal.Dispose(); m_TextureSourceNormal = null; // Load the source image m_imageSourceNormal = new ImageUtility.ImageFile( _FileName ); imagePanelNormalMap.Image = m_imageSourceNormal; uint W = m_imageSourceNormal.Width; uint H = m_imageSourceNormal.Height; // Build the source texture assuming the image is in linear space float4[] scanline = new float4[W]; PixelsBuffer sourceNormalMap = new PixelsBuffer( W*H*16 ); using ( System.IO.BinaryWriter Wr = sourceNormalMap.OpenStreamWrite() ) for ( uint Y=0; Y < H; Y++ ) { m_imageSourceNormal.ReadScanline( Y, scanline ); for ( uint X=0; X < W; X++ ) { Wr.Write( scanline[X].x ); Wr.Write( scanline[X].y ); Wr.Write( scanline[X].z ); Wr.Write( 1.0f ); } } m_TextureSourceNormal = new Texture2D( m_Device, W, H, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, new PixelsBuffer[] { sourceNormalMap } ); } catch ( Exception _e ) { MessageBox( "An error occurred while opening the normal map \"" + _FileName.FullName + "\":\n\n", _e ); } }
/// <summary> /// Builds many random values into a texture /// </summary> void BuildRandomTexture() { PixelsBuffer[] Content = new PixelsBuffer[4]; WMath.SimpleRNG.SetSeed( 561321987, 132194982 ); for ( int arrayIndex=0; arrayIndex < 4; arrayIndex++ ) { Content[arrayIndex] = new PixelsBuffer( HEIGHTFIELD_SIZE*HEIGHTFIELD_SIZE*4*System.Runtime.InteropServices.Marshal.SizeOf(typeof(float4)) ); using ( BinaryWriter W = Content[arrayIndex].OpenStreamWrite() ) for ( int Y=0; Y < HEIGHTFIELD_SIZE; Y++ ) { for ( int X=0; X < HEIGHTFIELD_SIZE; X++ ) { W.Write( (float) WMath.SimpleRNG.GetUniform() ); W.Write( (float) WMath.SimpleRNG.GetUniform() ); W.Write( (float) WMath.SimpleRNG.GetUniform() ); W.Write( (float) WMath.SimpleRNG.GetUniform() ); } } Content[arrayIndex].CloseStream(); } m_Tex_Random = new Texture2D( m_Device, HEIGHTFIELD_SIZE, HEIGHTFIELD_SIZE, 4, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, Content ); }
protected override void OnLoad( EventArgs e ) { base.OnLoad( e ); try { // Initialize the device m_device = new Device(); m_device.Init( graphPanel.Handle, false, true ); // Create the render shaders try { Shader.WarningAsError = false; m_shader_RenderSphere = new Shader( m_device, new System.IO.FileInfo( @"./Shaders/RenderSphere.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null ); m_shader_RenderScene = new Shader( m_device, new System.IO.FileInfo( @"./Shaders/RenderScene.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null ); m_shader_RenderLDR = new Shader( m_device, new System.IO.FileInfo( @"./Shaders/RenderLDR.hlsl" ), VERTEX_FORMAT.Pt4, "VS", null, "PS", null ); } catch ( Exception _e ) { throw new Exception( "Failed to compile shader! " + _e.Message ); } // Create CB m_CB_Render = new ConstantBuffer< CB_Main >( m_device, 0 ); // Create textures LoadHDRImage(); m_Tex_HDRBuffer = new Texture2D( m_device, (uint) graphPanel.Width, (uint) graphPanel.Height, 2, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, null ); { // Build noise texture SimpleRNG.SetSeed( 1U ); PixelsBuffer content = new PixelsBuffer( 256*256*16 ); using ( System.IO.BinaryWriter W = content.OpenStreamWrite() ) for ( int i=0; i < 256*256; i++ ) { W.Write( (float) SimpleRNG.GetUniform() ); W.Write( (float) SimpleRNG.GetUniform() ); W.Write( (float) SimpleRNG.GetUniform() ); W.Write( (float) SimpleRNG.GetUniform() ); } m_Tex_Noise = new Texture2D( m_device, 256, 256, 1, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, new PixelsBuffer[] { content } ); } // Build SH coeffs const int ORDERS = 20; { const int TABLE_SIZE = 64; // Load A coeffs into a texture array float[,,] A = new float[TABLE_SIZE,TABLE_SIZE,ORDERS]; // using ( System.IO.FileStream S = new System.IO.FileInfo( @"ConeTable_cosAO_order20.float" ).OpenRead() ) using ( System.IO.FileStream S = new System.IO.FileInfo( @"ConeTable_cosTheta_order20.float" ).OpenRead() ) using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) { for ( int thetaIndex=0; thetaIndex < TABLE_SIZE; thetaIndex++ ) for ( int AOIndex=0; AOIndex < TABLE_SIZE; AOIndex++ ) { for ( int order=0; order < ORDERS; order++ ) A[thetaIndex,AOIndex,order] = R.ReadSingle(); } } PixelsBuffer[] coeffSlices = new PixelsBuffer[5]; // 5 slices of 4 coeffs each to get our 20 orders for ( int sliceIndex=0; sliceIndex < coeffSlices.Length; sliceIndex++ ) { PixelsBuffer coeffSlice = new PixelsBuffer( TABLE_SIZE*TABLE_SIZE*16 ); coeffSlices[sliceIndex] = coeffSlice; using ( System.IO.BinaryWriter W = coeffSlice.OpenStreamWrite() ) { for ( int thetaIndex=0; thetaIndex < TABLE_SIZE; thetaIndex++ ) for ( int AOIndex=0; AOIndex < TABLE_SIZE; AOIndex++ ) { W.Write( A[thetaIndex,AOIndex,4*sliceIndex+0] ); W.Write( A[thetaIndex,AOIndex,4*sliceIndex+1] ); W.Write( A[thetaIndex,AOIndex,4*sliceIndex+2] ); W.Write( A[thetaIndex,AOIndex,4*sliceIndex+3] ); } } } m_Tex_ACoeffs = new Texture2D( m_device, 64, 64, coeffSlices.Length, 1, PIXEL_FORMAT.RGBA32_FLOAT, false, false, coeffSlices ); } { // Load environment coeffs into a constant buffer float3[] coeffs = new float3[ORDERS*ORDERS]; using ( System.IO.FileStream S = new System.IO.FileInfo( @"Ennis_order20.float3" ).OpenRead() ) using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) for ( int coeffIndex=0; coeffIndex < ORDERS*ORDERS; coeffIndex++ ) coeffs[coeffIndex].Set( R.ReadSingle(), R.ReadSingle(), R.ReadSingle() ); // Write into a raw byte[] byte[] rawContent = new byte[400 * 4 * 4]; using ( System.IO.MemoryStream MS = new System.IO.MemoryStream( rawContent ) ) using ( System.IO.BinaryWriter W = new System.IO.BinaryWriter( MS ) ) { for ( int coeffIndex=0; coeffIndex < ORDERS*ORDERS; coeffIndex++ ) { W.Write( coeffs[coeffIndex].x ); W.Write( coeffs[coeffIndex].y ); W.Write( coeffs[coeffIndex].z ); W.Write( 0.0f ); } } m_CB_Coeffs = new RawConstantBuffer( m_device, 1, rawContent.Length ); m_CB_Coeffs.UpdateData( rawContent ); } // Create camera + manipulator m_camera.CreatePerspectiveCamera( 0.5f * (float) Math.PI, (float) graphPanel.Width / graphPanel.Height, 0.01f, 100.0f ); m_camera.CameraTransformChanged += m_camera_CameraTransformChanged; m_cameraManipulator.Attach( graphPanel, m_camera ); m_cameraManipulator.InitializeCamera( -2.0f * float3.UnitZ, float3.Zero, float3.UnitY ); m_camera_CameraTransformChanged( null, EventArgs.Empty ); // Start rendering Application.Idle += Application_Idle; } catch ( Exception _e ) { MessageBox.Show( "Failed to initialize D3D renderer!\r\nReason: " + _e.Message ); } }
public Texture2D PipoImage2Texture( System.IO.FileInfo _FileName ) { using ( System.IO.FileStream S = _FileName.OpenRead() ) using ( System.IO.BinaryReader R = new System.IO.BinaryReader( S ) ) { int W, H; W = R.ReadInt32(); H = R.ReadInt32(); PixelsBuffer Buff = new PixelsBuffer( (uint) (4 * W * H * 4) ); using ( System.IO.BinaryWriter Wr = Buff.OpenStreamWrite() ) { float4 C = new float4(); for ( int Y=0; Y < H; Y++ ) { for ( int X=0; X < W; X++ ) { C.x = R.ReadSingle(); C.y = R.ReadSingle(); C.z = R.ReadSingle(); C.w = R.ReadSingle(); Wr.Write( C.x ); Wr.Write( C.y ); Wr.Write( C.z ); Wr.Write( C.w ); } } } return Image2Texture( (uint) W, (uint) H, PIXEL_FORMAT.RGBA32_FLOAT, Buff ); } }
public Texture2D Image2Texture( int _Width, int _Height, byte[] _Content ) { using ( PixelsBuffer Buff = new PixelsBuffer( _Content.Length ) ) { using ( System.IO.BinaryWriter W = Buff.OpenStreamWrite() ) W.Write( _Content ); return Image2Texture( _Width, _Height, Buff ); } }