@@ -5,11 +5,6 @@ namespace Unilight
55 // 1st = Origin, 2nd = Direction
66 using Ray = Tuple < Vector3D , Vector3D > ;
77
8- using IntPair = Tuple < int , int > ;
9-
10- // Eye, LookAt, ViewportWidth, ViewportHeight
11- using TCamera = Tuple < Vector3D , Vector3D , float , float > ;
12-
138 public class Raytracer
149 {
1510 private static int DEFAULT_TRACE_DEPTH = 5 ;
@@ -37,6 +32,8 @@ private struct RayTraversalResult
3732
3833 private Intersector mIntersector = new Intersector ( ) ;
3934
35+ private Matrix4 ? _imageToWorld = null ;
36+
4037 public bool GlobalReflection { get ; set ; } = true ;
4138 public bool ComputeSpecular { get ; set ; } = false ;
4239 public bool ComputeDiffuse { get ; set ; } = false ;
@@ -45,7 +42,9 @@ private struct RayTraversalResult
4542
4643 public int TraceDepth { get ; set ; } = DEFAULT_TRACE_DEPTH ;
4744
48- public Raytracer ( ) { }
45+ public Raytracer ( )
46+ {
47+ }
4948
5049 private RgbColor computeSpecular ( float vDotR , float mGls , RgbColor sourceSpec , float matSpec )
5150 {
@@ -141,38 +140,46 @@ private RgbColor trace(Ray ray, int depth)
141140 return lit ;
142141 }
143142
144- private Matrix4 imageToViewportTransform ( int imgWidth , int imgHeight , Camera cam )
143+ private void ComputeImageToViewportTransform ( int imageWidth , int imageHeight , out Matrix4 result )
145144 {
146- float width = cam . ViewportWidth ;
147- float height = cam . ViewportHeight ;
148- if ( imgWidth == 0 || imgHeight == 0 || width == 0 || height == 0 )
149- return Matrix4 . identity ( ) ;
145+ float width = Camera . ViewportWidth ;
146+ float height = Camera . ViewportHeight ;
150147
151- Matrix4 finalTransform = Matrix4 . translate ( cam . LookAt . X , cam . LookAt . Y , cam . LookAt . Z ) ;
148+ if ( imageWidth == 0 || imageHeight == 0 || width == 0 || height == 0 )
149+ {
150+ result = Matrix4 . identity ( ) ;
151+ return ;
152+ }
153+
154+ Matrix4 finalTransform = Matrix4 . translate ( Camera . LookAt . X , Camera . LookAt . Y , Camera . LookAt . Z ) ;
152155
153- Vector3D invNormal = cam . Eye - cam . LookAt ;
156+ Vector3D invNormal = Camera . Eye - Camera . LookAt ;
154157 invNormal . Normalize ( ) ;
155158
156159 Matrix4 scale = Matrix4 . identity ( ) ;
157- scale . SetAt ( 0 , 0 , width / imgWidth ) ;
158- scale . SetAt ( 1 , 1 , height / imgHeight ) ;
160+ scale . SetAt ( 0 , 0 , width / imageWidth ) ;
161+ scale . SetAt ( 1 , 1 , height / imageHeight ) ;
159162 finalTransform . MultiplyThisBy ( scale ) ;
160163
161164 Matrix4 mirror = Matrix4 . identity ( ) ;
162165 mirror . SetAt ( 1 , 1 , - 1 ) ;
163166 finalTransform . MultiplyThisBy ( mirror ) ;
164167
165- Matrix4 center = Matrix4 . translate ( - imgWidth / 2 , - imgHeight / 2 , 0 ) ;
168+ Matrix4 center = Matrix4 . translate ( - imageWidth / 2 , - imageHeight / 2 , 0 ) ;
166169 finalTransform . MultiplyThisBy ( center ) ;
167170
168- return finalTransform ;
171+ // assign to out parameter
172+ result = finalTransform ;
169173 }
170174
171175 public void Render ( )
172176 {
173177 if ( Buffer == null )
174178 return ;
175179
180+ // Compute image to world transform
181+ ComputeImageToViewportTransform ( Buffer . Width , Buffer . Height , out _imageToWorld ) ;
182+
176183 List < ( Point start , Point end ) > ? chunks = null ;
177184 Chunks . CreateRenderChunks ( Buffer . Width , Buffer . Height , out chunks ) ;
178185
@@ -191,10 +198,10 @@ public void Render()
191198 //PixelsToPlotCount = Buffer.Width * Buffer.Height;
192199
193200 // Render all chunks in parallel
194- // Parallel.ForEach(chunks, chunk =>
195- // {
196- // RenderChunk(chunk.start, chunk.end, pixels, stride);
197- // });
201+ Parallel . ForEach ( chunks , chunk =>
202+ {
203+ RenderChunk ( chunk . start , chunk . end , pixels , stride ) ;
204+ } ) ;
198205
199206 RenderChunk ( new Point ( 0 , 0 ) , new Point ( Buffer . Width , Buffer . Height ) , pixels , stride ) ;
200207
@@ -217,12 +224,9 @@ private void RenderChunk(Point start, Point end, byte[] pixels, int stride)
217224
218225 PixelIterator iter = new PixelIterator ( start , end , TraversalOrder ) ;
219226
220- // TBD: Compute this only once, not for every thread
221- Matrix4 i2v = imageToViewportTransform ( Buffer . Width , Buffer . Height , Camera ) ;
222-
223227 while ( ! iter . Done ( ) )
224228 {
225- Vector3D mapped = i2v . Multiply ( new Vector3D ( iter . Cursor . X , iter . Cursor . Y , 0 ) ) ;
229+ Vector3D mapped = _imageToWorld . Multiply ( new Vector3D ( iter . Cursor . X , iter . Cursor . Y , 0 ) ) ;
226230 Vector3D dir = mapped - Camera . Eye ;
227231 dir . Normalize ( ) ;
228232 Ray ray = new Ray ( Camera . Eye , dir ) ;
0 commit comments