Skip to content

Commit f28a789

Browse files
committed
Using RenderChunks before going parellel
1 parent 7505c4c commit f28a789

File tree

1 file changed

+71
-38
lines changed

1 file changed

+71
-38
lines changed

Engine/Raytracer.cs

Lines changed: 71 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
/*
2-
* The actual raytracing algorithm
3-
*/
1+
using CommonGraphics;
2+
43
namespace UnilightRaytracer
54
{
65
// 1st = Origin, 2nd = Direction
@@ -15,6 +14,9 @@ public class Raytracer
1514
{
1615
private static int DEFAULT_TRACE_DEPTH = 5;
1716

17+
// pixel traversal order
18+
public TraversalOrder TraversalOrder { get; set; }
19+
1820
private struct RayTraversalResult
1921
{
2022
public GObject? Closest { get; set; }
@@ -25,11 +27,11 @@ private struct RayTraversalResult
2527
public delegate void UpdateCallback(int percent);
2628

2729
public UpdateCallback? Callback { get; set; } = null;
28-
30+
2931
public Camera Camera { get; set; } = new Camera();
30-
32+
3133
public Scene? Scene { get; set; } = null;
32-
34+
3335
// Reference to the Bitmap we're drawing to
3436
public Bitmap? Buffer { get; set; } = null;
3537

@@ -65,7 +67,7 @@ private Color trace(Ray ray, int depth)
6567

6668
GObject? closest = null;
6769
float dist = float.MaxValue;
68-
Vector intersectionPoint = new ();
70+
Vector intersectionPoint = new();
6971

7072
for (int k = 0; k < Scene.CountObjects(); ++k)
7173
{
@@ -171,45 +173,76 @@ public void Render()
171173
if (Buffer == null)
172174
return;
173175

174-
int imgWidth = Buffer.Width;
175-
int imgHeight = Buffer.Height;
176-
long total = imgWidth * imgHeight;
177-
if (total <= 0) return;
176+
List<(Point start, Point end)>? chunks = null;
177+
Chunks.CreateRenderChunks(Buffer.Width, Buffer.Height, out chunks);
178178

179-
float factor = 100.0f / total;
180-
int lastPercent = 0;
181-
long count = 0;
179+
if (chunks == null)
180+
return;
182181

183-
Matrix4 i2v = imageToViewportTransform(imgWidth, imgHeight, Camera);
184-
185-
for (int p = 0; !mStopRender && p < imgWidth; ++p)
186-
{
187-
for (int q = 0; !mStopRender && q < imgHeight; ++q)
188-
{
189-
int percent = (int)(count * factor);
190-
if (percent != lastPercent && Callback != null) Callback(percent);
191-
lastPercent = percent;
182+
// Lock the bitmap once
183+
var rect = new Rectangle(0, 0, Buffer.Width, Buffer.Height);
184+
var bmpData = Buffer.LockBits(rect, System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
192185

193-
Vector mapped = i2v.Multiply(new Vector(p, q, 0));
194-
Vector dir = mapped - Camera.Eye;
195-
dir.Normalize();
196-
Ray ray = new Ray(Camera.Eye, dir);
186+
IntPtr ptr = bmpData.Scan0;
187+
int stride = bmpData.Stride;
188+
byte[] pixels = new byte[stride * Buffer.Height];
197189

198-
Color c = trace(ray, 1);
190+
//_plottedPixels = 0;
191+
//PixelsToPlotCount = Buffer.Width * Buffer.Height;
199192

200-
Buffer.SetPixel(p, q, System.Drawing.Color.FromArgb(
201-
(int)Math.Round(c.r * 255),
202-
(int)Math.Round(c.g * 255),
203-
(int)Math.Round(c.b * 255)
204-
));
193+
// Render all chunks in parallel
194+
//Parallel.ForEach(chunks, chunk =>
195+
//{
196+
// RenderChunk(chunk.start, chunk.end, pixels, stride);
197+
//});
205198

206-
++count;
207-
}
208-
}
199+
RenderChunk(new Point(0, 0), new Point(Buffer.Width, Buffer.Height), pixels, stride);
200+
201+
// Copy back into bitmap
202+
System.Runtime.InteropServices.Marshal.Copy(pixels, 0, ptr, pixels.Length);
203+
Buffer.UnlockBits(bmpData);
209204

210-
Callback?.Invoke(100);
211-
mStopRender = false;
205+
// 100% progress
206+
//CallbackProgress?.Invoke(100);
212207
}
213208

209+
private void RenderChunk(Point start, Point end, byte[] pixels, int stride)
210+
{
211+
if (Buffer == null)
212+
return;
213+
214+
// Compute width and height
215+
int width = end.X - start.X;
216+
int height = end.Y - start.Y;
217+
218+
PixelIterator iter = new PixelIterator(start, end, TraversalOrder);
219+
220+
// TBD: Compute this only once, not for every thread
221+
Matrix4 i2v = imageToViewportTransform(Buffer.Width, Buffer.Height, Camera);
222+
223+
while (!iter.Done())
224+
{
225+
Vector mapped = i2v.Multiply(new Vector(iter.Cursor.X, iter.Cursor.Y, 0));
226+
Vector dir = mapped - Camera.Eye;
227+
dir.Normalize();
228+
Ray ray = new Ray(Camera.Eye, dir);
229+
230+
Color c = trace(ray, 1);
231+
232+
// Write into pixel array (thread-safe)
233+
int index = iter.Cursor.Y * stride + iter.Cursor.X * 4;
234+
pixels[index + 0] = (byte)(c.b * 255);
235+
pixels[index + 1] = (byte)(c.g * 255);
236+
pixels[index + 2] = (byte)(c.r * 255);
237+
pixels[index + 3] = 255; // full opacity
238+
239+
// Thread-safe progress update
240+
//int plotted = Interlocked.Increment(ref _plottedPixels);
241+
//int percent = (int)((plotted / (double)PixelsToPlotCount) * 100);
242+
243+
// Advance iterator
244+
iter.Step();
245+
}
246+
}
214247
}
215248
}

0 commit comments

Comments
 (0)