Rasterizer.cs 20.2 KB
Newer Older
H
Init  
happyfire 已提交
1 2 3 4 5 6 7 8 9 10 11 12
using System;
using System.Collections.Generic;
using UnityEngine;

namespace URasterizer
{
    public enum BufferMask
    {
        Color = 1,
        Depth = 2
    }

H
happyfire 已提交
13 14
    public delegate void OnRasterizerStatUpdate(int verticesAll, int trianglesAll, int trianglesRendered);

H
Init  
happyfire 已提交
15 16 17 18 19
    public class Rasterizer
    {
        int _width;
        int _height;

H
happyfire 已提交
20
        RenderingConfig _config;
H
Init  
happyfire 已提交
21 22 23 24 25 26 27

        Matrix4x4 _matModel;
        Matrix4x4 _matView;
        Matrix4x4 _matProjection;

        public Matrix4x4 ModelMatrix
        {
H
happyfire 已提交
28 29
            get => _matModel;           
            set => _matModel = value;            
H
Init  
happyfire 已提交
30 31 32 33
        }

        public Matrix4x4 ViewMatrix
        {
H
happyfire 已提交
34 35
            get => _matView;
            set => _matView = value;
H
Init  
happyfire 已提交
36 37 38 39
        }

        public Matrix4x4 ProjectionMatrix
        {
H
happyfire 已提交
40 41
            get => _matProjection;
            set => _matProjection = value;
H
Init  
happyfire 已提交
42 43 44 45
        }

        Color[] frame_buf;
        float[] depth_buf;
H
happyfire 已提交
46
        Color[] temp_buf;
H
Init  
happyfire 已提交
47

H
happyfire 已提交
48
        public Texture2D texture;        
H
Init  
happyfire 已提交
49

H
clip  
happyfire 已提交
50
        //Stats
H
happyfire 已提交
51 52 53 54 55
        int _trianglesAll, _trianglesRendered;
        int _verticesAll;

        public OnRasterizerStatUpdate StatDelegate;

H
clip  
happyfire 已提交
56

H
happyfire 已提交
57
        public Rasterizer(int w, int h, RenderingConfig config)
H
Init  
happyfire 已提交
58
        {
H
happyfire 已提交
59 60
            Debug.Log($"Rasterizer screen size: {w}x{h}");

H
happyfire 已提交
61 62
            _config = config;

H
Init  
happyfire 已提交
63 64 65 66 67
            _width = w;
            _height = h;

            frame_buf = new Color[w * h];
            depth_buf = new float[w * h];
H
happyfire 已提交
68
            temp_buf = new Color[w * h];
H
Init  
happyfire 已提交
69 70 71 72 73 74 75 76 77

            texture = new Texture2D(w, h);
            texture.filterMode = FilterMode.Point;
        }

        public float Aspect
        {
            get
            {
H
clip  
happyfire 已提交
78
                return (float)_width / _height;
H
Init  
happyfire 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
            }
        }

        void FillArray<T>(T[] arr, T value)
        {
            int i = 0;
            if(arr.Length > 16)
            {
                do
                {
                    arr[i++] = value;
                } while (i < arr.Length);

                while( i + 16 < arr.Length)
                {
                    Array.Copy(arr, 0, arr, i, 16);
                    i += 16;
                }
            }
            while (i < arr.Length)
            {
                arr[i++] = value;
            }
        }

        public void Clear(BufferMask mask)
        {
            if((mask & BufferMask.Color) == BufferMask.Color)
            {                
H
happyfire 已提交
108
                FillArray(frame_buf, _config.ClearColor);
H
Init  
happyfire 已提交
109 110 111
            }
            if((mask & BufferMask.Depth) == BufferMask.Depth)
            {
H
happyfire 已提交
112
                FillArray(depth_buf, 0f);
H
Init  
happyfire 已提交
113
            }
H
happyfire 已提交
114 115 116

            _trianglesAll = _trianglesRendered = 0;
            _verticesAll = 0;
H
Init  
happyfire 已提交
117 118 119 120
        }

        public void SetupViewProjectionMatrix(Camera camera)
        {
H
happyfire 已提交
121
            //左手坐标系转右手坐标系,以下坐标和向量z取反
H
Init  
happyfire 已提交
122
            var camPos = camera.transform.position;
H
happyfire 已提交
123 124 125 126 127 128 129
            camPos.z *= -1; 
            var lookAt = camera.transform.forward;
            lookAt.z *= -1;
            var up = camera.transform.up;
            up.z *= -1;
            
            ViewMatrix = TransformTool.GetViewMatrix(camPos, lookAt, up);
H
Init  
happyfire 已提交
130 131 132

            if (camera.orthographic)
            {
H
happyfire 已提交
133 134
                float halfOrthHeight = camera.orthographicSize;
                float halfOrthWidth = halfOrthHeight * Aspect;
H
Init  
happyfire 已提交
135 136
                float f = -camera.farClipPlane;
                float n = -camera.nearClipPlane;
H
happyfire 已提交
137
                ProjectionMatrix = TransformTool.GetOrthographicProjectionMatrix(-halfOrthWidth, halfOrthWidth, -halfOrthHeight, halfOrthHeight, f, n);
H
Init  
happyfire 已提交
138 139 140
            }
            else
            {
H
happyfire 已提交
141
                ProjectionMatrix = TransformTool.GetPerspectiveProjectionMatrix(camera.fieldOfView, Aspect, camera.nearClipPlane, camera.farClipPlane);
H
Init  
happyfire 已提交
142 143 144
            }
        }

H
happyfire 已提交
145
        public void Draw(RenderingObject ro, Camera camera)
H
Init  
happyfire 已提交
146
        {
H
happyfire 已提交
147
            Mesh mesh = ro.mesh;
H
Init  
happyfire 已提交
148 149
            SetupViewProjectionMatrix(camera);

H
happyfire 已提交
150
            ModelMatrix = ro.GetModelMatrix();                      
H
Init  
happyfire 已提交
151 152 153

            Matrix4x4 mvp = _matProjection * _matView * _matModel;

H
happyfire 已提交
154 155 156 157 158 159 160 161
            _verticesAll += mesh.vertexCount;
            _trianglesAll += mesh.triangles.Length / 3;

            //Unity模型本地坐标系也是左手系,需要转成我们使用的右手系
            //1. z轴反转
            //2. 三角形顶点环绕方向从顺时针改成逆时针


H
happyfire 已提交
162
            /// ------------- Vertex Shader -------------------
H
happyfire 已提交
163 164 165 166 167 168 169
            Vector4[] csVertices = new Vector4[mesh.vertexCount]; //clip space vertices
            for(int i=0; i<mesh.vertexCount; ++i)
            {                
                var vert = mesh.vertices[i];                
                csVertices[i] = mvp * new Vector4(vert.x, vert.y, -vert.z, 1); //注意这儿反转了z坐标
            }

H
happyfire 已提交
170

H
Init  
happyfire 已提交
171 172
            var indices = mesh.triangles;
            for(int i=0; i< indices.Length; i+=3)
H
happyfire 已提交
173 174 175
            {         
                /// -------------- Primitive Assembly -----------------

H
happyfire 已提交
176 177 178 179 180
                //注意这儿对调了v0和v1的索引,因为原来的 0,1,2是顺时针的,对调后是 1,0,2是逆时针的
                //Unity Quard模型的两个三角形索引分别是 0,3,1,3,0,2 转换后为 3,0,1,0,3,2
                int idx0 = indices[i+1];
                int idx1 = indices[i]; 
                int idx2 = indices[i+2];
H
happyfire 已提交
181
                             
H
Init  
happyfire 已提交
182 183
                Vector4[] v =
                {
H
happyfire 已提交
184 185 186
                    csVertices[idx0],
                    csVertices[idx1],
                    csVertices[idx2]                   
H
Init  
happyfire 已提交
187
                };
H
happyfire 已提交
188
                
H
clip  
happyfire 已提交
189

H
happyfire 已提交
190
                // ------ Clipping -------
H
clip  
happyfire 已提交
191 192 193
                if (Clipped(v))
                {
                    continue;
H
happyfire 已提交
194 195 196 197 198
                }

                // ------- Perspective division --------
                //clip space to NDC
                for (int k=0; k<3; k++)
H
Init  
happyfire 已提交
199 200 201
                {
                    v[k].x /= v[k].w;
                    v[k].y /= v[k].w;
H
happyfire 已提交
202 203 204 205
                    v[k].z /= v[k].w;                  
                }

                //backface culling
H
happyfire 已提交
206
                if (_config.BackfaceCulling && !ro.DoubleSideRendering)
H
happyfire 已提交
207
                {
208 209 210 211 212 213
                    Vector3 v0 = new Vector3(v[0].x, v[0].y, v[0].z);
                    Vector3 v1 = new Vector3(v[1].x, v[1].y, v[1].z);
                    Vector3 v2 = new Vector3(v[2].x, v[2].y, v[2].z);
                    Vector3 e01 = v1 - v0;
                    Vector3 e02 = v2 - v0;
                    Vector3 cross = Vector3.Cross(e01, e02);
H
happyfire 已提交
214
                    if (cross.z < 0)
215 216 217
                    {
                        continue;
                    }
H
Init  
happyfire 已提交
218 219
                }

H
happyfire 已提交
220 221
                ++_trianglesRendered;

H
happyfire 已提交
222 223
                // ------- Viewport Transform ----------
                //NDC to screen space
H
Init  
happyfire 已提交
224 225 226 227 228
                for (int k = 0; k < 3; k++)
                {
                    var vec = v[k];
                    vec.x = 0.5f * _width * (vec.x + 1.0f);
                    vec.y = 0.5f * _height * (vec.y + 1.0f);
H
happyfire 已提交
229

H
happyfire 已提交
230 231 232 233 234 235 236 237 238 239
                    //在硬件渲染中,NDC的z值经过硬件的透视除法之后就直接写入到depth buffer了,如果要调整需要在投影矩阵中调整
                    //由于我们是软件渲染,所以可以在这里调整z值。                    

                    //GAMES101约定的NDC是右手坐标系,z值范围是[-1,1],但n为1,f为-1,因此值越大越靠近n。                    
                    //为了可视化Depth buffer,将最终的z值从[-1,1]映射到[0,1]的范围,因此最终n为1, f为0。离n越近,深度值越大。                    
                    //由于远处的z值为0,因此clear时深度要清除为0,然后深度测试时,使用GREATER测试。
                    //(当然我们也可以在这儿反转z值,然后clear时使用1清除,并且深度测试时使用LESS_EQUAL测试)
                    //注意:这儿的z值调整并不是必要的,只是为了可视化时便于映射为颜色值。其实也可以在可视化的地方调整。
                    //但是这么调整后,正好和Unity在DirectX平台的Reverse z一样,让near plane附近的z值的浮点数精度提高。
                    vec.z = vec.z * 0.5f + 0.5f; 
H
happyfire 已提交
240

H
Init  
happyfire 已提交
241 242 243
                    v[k] = vec;
                }

H
happyfire 已提交
244
             
H
Init  
happyfire 已提交
245 246 247 248 249
                Triangle t = new Triangle();
                for(int k=0; k<3; k++)
                {
                    t.SetPosition(k, v[k]);
                }
H
happyfire 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264

                //设置顶点色,使用config中的颜色数组循环设置
                int vertexColorCount = _config.VertexColors.Length;
                if(vertexColorCount > 0)
                {
                    t.SetColor(0, _config.VertexColors[idx0 % vertexColorCount]);
                    t.SetColor(1, _config.VertexColors[idx1 % vertexColorCount]);
                    t.SetColor(2, _config.VertexColors[idx2 % vertexColorCount]);
                }
                else
                {
                    t.SetColor(0, Color.white);
                    t.SetColor(1, Color.white);
                    t.SetColor(2, Color.white);
                }                             
H
Init  
happyfire 已提交
265

H
happyfire 已提交
266
                /// ---------- Rasterization -----------
H
happyfire 已提交
267
                if (_config.WireframeMode)
H
Init  
happyfire 已提交
268
                {
H
happyfire 已提交
269
                    RasterizeWireframe(t);
H
Init  
happyfire 已提交
270 271 272
                }
                else
                {
H
happyfire 已提交
273
                    RasterizeTriangle(t);
H
Init  
happyfire 已提交
274 275 276 277 278
                }
                
            }
        }

H
clip  
happyfire 已提交
279 280
        bool Clipped(Vector4[] v)
        {
281 282 283
            //Clip space使用GAMES101规范,右手坐标系,n为+1, f为-1
            //裁剪(仅整体剔除)     
            //实际的硬件是在Clip space裁剪,所以此处我们也使用clip space (当然由于我们不真正的裁剪,只是整体剔除,所以其实在NDC操作更方便)
H
clip  
happyfire 已提交
284 285 286
            for (int i = 0; i < 3; ++i)
            {
                var vertex = v[i];
287
                var w = vertex.w;
H
comment  
happyfire 已提交
288
                w = w >= 0 ? w : -w; //由于NDC中总是满足-1<=Zndc<=1, 而当 w < 0 时,-w >= Zclip = Zndc*w >= w。所以此时clip space的坐标范围是[w,-w], 为了比较时更明确,将w取正
289
                //Debug.LogError("w=" + w);
H
clip  
happyfire 已提交
290 291 292 293 294 295 296 297 298 299 300 301 302 303
                bool inside = (vertex.x <= w && vertex.x >= -w
                    && vertex.y <= w && vertex.y >= -w
                    && vertex.z <= w && vertex.z >= -w);
                if (inside)
                {             
                    //不裁剪三角形,只要有任意一点在clip space中则三角形整体保留
                    return false;
                }
            }

            //三个顶点都不在三角形中则剔除
            return true;
        }

H
Init  
happyfire 已提交
304
        #region Wireframe mode
H
happyfire 已提交
305
        //Breshham算法画线,颜色使用线性插值(非透视校正)
H
happyfire 已提交
306
        private void DrawLine(Vector3 begin, Vector3 end, Color colorBegin, Color colorEnd)
H
Init  
happyfire 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319
        {            
            int x1 = Mathf.FloorToInt(begin.x);
            int y1 = Mathf.FloorToInt(begin.y);
            int x2 = Mathf.FloorToInt(end.x);
            int y2 = Mathf.FloorToInt(end.y);            

            int x, y, dx, dy, dx1, dy1, px, py, xe, ye, i;

            dx = x2 - x1;
            dy = y2 - y1;
            dx1 = Math.Abs(dx);
            dy1 = Math.Abs(dy);
            px = 2 * dy1 - dx1;
H
happyfire 已提交
320 321 322 323
            py = 2 * dx1 - dy1;

            Color c1 = colorBegin;
            Color c2 = colorEnd;
H
Init  
happyfire 已提交
324 325 326 327 328 329 330 331 332 333 334 335 336 337

            if (dy1 <= dx1)
            {
                if (dx >= 0)
                {
                    x = x1;
                    y = y1;
                    xe = x2;
                }
                else
                {
                    x = x2;
                    y = y2;
                    xe = x1;
H
happyfire 已提交
338 339
                    c1 = colorEnd;
                    c2 = colorBegin;
H
Init  
happyfire 已提交
340
                }
H
happyfire 已提交
341 342
                Vector3 point = new Vector3(x, y, 1.0f);                 
                SetPixel(point, c1);
H
Init  
happyfire 已提交
343 344
                for (i = 0; x < xe; i++)
                {
H
happyfire 已提交
345
                    x++;
H
Init  
happyfire 已提交
346 347
                    if (px < 0)
                    {
H
happyfire 已提交
348
                        px += 2 * dy1;
H
Init  
happyfire 已提交
349 350 351 352 353
                    }
                    else
                    {
                        if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
                        {
H
happyfire 已提交
354
                            y++;
H
Init  
happyfire 已提交
355 356 357
                        }
                        else
                        {
H
happyfire 已提交
358
                            y--;
H
Init  
happyfire 已提交
359
                        }
H
happyfire 已提交
360
                        px +=  2 * (dy1 - dx1);
H
Init  
happyfire 已提交
361 362 363
                    }
                    
                    Vector3 pt = new Vector3(x, y, 1.0f);
H
happyfire 已提交
364 365
                    float t = 1.0f - (float)(xe - x) / dx1;
                    Color line_color = Color.Lerp(c1, c2, t);                    
H
Init  
happyfire 已提交
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
                    SetPixel(pt, line_color);
                }
            }
            else
            {
                if (dy >= 0)
                {
                    x = x1;
                    y = y1;
                    ye = y2;
                }
                else
                {
                    x = x2;
                    y = y2;
                    ye = y1;
H
happyfire 已提交
382 383
                    c1 = colorEnd;
                    c2 = colorBegin;
H
Init  
happyfire 已提交
384
                }
H
happyfire 已提交
385 386
                Vector3 point = new Vector3(x, y, 1.0f);                
                SetPixel(point, c1);
H
happyfire 已提交
387
                
H
Init  
happyfire 已提交
388 389
                for (i = 0; y < ye; i++)
                {
H
happyfire 已提交
390
                    y++;
H
Init  
happyfire 已提交
391 392
                    if (py <= 0)
                    {
H
happyfire 已提交
393
                        py += 2 * dx1;
H
Init  
happyfire 已提交
394 395 396 397 398
                    }
                    else
                    {
                        if ((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
                        {
H
happyfire 已提交
399
                            x++;
H
Init  
happyfire 已提交
400 401 402
                        }
                        else
                        {
H
happyfire 已提交
403
                            x--;
H
Init  
happyfire 已提交
404
                        }
H
happyfire 已提交
405
                        py += 2 * (dx1 - dy1);
H
Init  
happyfire 已提交
406 407
                    }
                    Vector3 pt = new Vector3(x, y, 1.0f);
H
happyfire 已提交
408 409
                    float t = 1.0f - (float)(ye - y) / dy1;
                    Color line_color = Color.Lerp(c1, c2, t);
H
Init  
happyfire 已提交
410 411 412 413 414
                    SetPixel(pt, line_color);
                }
            }
        }

H
happyfire 已提交
415
        private void RasterizeWireframe(Triangle t)
H
Init  
happyfire 已提交
416
        {
H
happyfire 已提交
417 418 419
            DrawLine(t.Positions[0], t.Positions[1], t.Colors[0], t.Colors[1]);
            DrawLine(t.Positions[1], t.Positions[2], t.Colors[1], t.Colors[2]);
            DrawLine(t.Positions[2], t.Positions[0], t.Colors[2], t.Colors[0]);
H
Init  
happyfire 已提交
420 421 422 423
        }

        #endregion

H
clip  
happyfire 已提交
424 425
        

H
Init  
happyfire 已提交
426
        //Screen space  rasterization
H
happyfire 已提交
427
        void RasterizeTriangle(Triangle t)
H
Init  
happyfire 已提交
428 429
        {
            var v = t.Positions;
H
clip  
happyfire 已提交
430
            
H
Init  
happyfire 已提交
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
            //Find out the bounding box of current triangle.
            float minX = v[0].x;
            float maxX = minX;
            float minY = v[0].y;
            float maxY = minY;

            for(int i=1; i<3; ++i)
            {
                float x = v[i].x;
                if(x < minX)
                {
                    minX = x;
                } else if(x > maxX)
                {
                    maxX = x;
                }
                float y = v[i].y;
                if(y < minY)
                {
                    minY = y;
                }else if(y > maxY)
                {
                    maxY = y;
                }
            }

            int minPX = Mathf.FloorToInt(minX);
            minPX = minPX < 0 ? 0 : minPX;
            int maxPX = Mathf.CeilToInt(maxX);
            maxPX = maxPX > _width ? _width : maxPX;
            int minPY = Mathf.FloorToInt(minY);
            minPY = minPY < 0 ? 0 : minPY;
            int maxPY = Mathf.CeilToInt(maxY);
            maxPY = maxPY > _height ? _height : maxPY;

H
happyfire 已提交
466
  
H
clip  
happyfire 已提交
467
            {                
H
Init  
happyfire 已提交
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
                // 遍历当前三角形包围中的所有像素,判断当前像素是否在三角形中
                // 对于在三角形中的像素,使用重心坐标插值得到深度值,并使用z buffer进行深度测试和写入
                for(int y = minPY; y < maxPY; ++y)
                {
                    for(int x = minPX; x < maxPX; ++x)
                    {
                        if(IsInsideTriangle(x, y, t))
                        {
                            //计算重心坐标
                            var c = ComputeBarycentric2D(x, y, t);
                            float alpha = c.x;
                            float beta = c.y;
                            float gamma = c.z;
                            //透视校正插值
                            float w_reciprocal = 1.0f / (alpha / v[0].w + beta / v[1].w + gamma / v[2].w);
                            float z_interpolated = alpha * v[0].z / v[0].w + beta * v[1].z / v[1].w + gamma * v[2].z / v[2].w;
                            z_interpolated *= w_reciprocal;
H
happyfire 已提交
485
                            //深度测试(注意我们这儿的z值越大越靠近near plane,因此大值通过测试)
H
Init  
happyfire 已提交
486
                            int index = GetIndex(x, y);
H
happyfire 已提交
487
                            if(z_interpolated > depth_buf[index])
H
Init  
happyfire 已提交
488
                            {
H
happyfire 已提交
489
                                depth_buf[index] = z_interpolated;
H
happyfire 已提交
490
                                
H
Init  
happyfire 已提交
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
                                Color color_interpolated = alpha * t.Colors[0] / v[0].w + beta * t.Colors[1] / v[1].w + gamma * t.Colors[2] / v[2].w;
                                color_interpolated *= w_reciprocal;
                                frame_buf[index] = color_interpolated;
                            }
                        }                        
                    }
                }
            }
        }

        bool IsInsideTriangle(int x, int y, Triangle t, float offsetX=0.5f, float offsetY=0.5f)
        {
            Vector3[] v = new Vector3[3];
            for(int i=0; i<3; ++i)
            {
                v[i] = new Vector3(t.Positions[i].x, t.Positions[i].y, t.Positions[i].z);
            }

            //当前像素中心位置p
            Vector3 p = new Vector3(x + offsetX, y + offsetY, 0);            
            
            Vector3 v0p = p - v[0]; v0p[2] = 0;
            Vector3 v01 = v[1] - v[0]; v01[2] = 0;
            Vector3 cross0p = Vector3.Cross(v0p, v01);

            Vector3 v1p = p - v[1]; v1p[2] = 0;
            Vector3 v12 = v[2] - v[1]; v12[2] = 0;
            Vector3 cross1p = Vector3.Cross(v1p, v12);

            if(cross0p.z * cross1p.z > 0)
            {
                Vector3 v2p = p - v[2]; v2p[2] = 0;
                Vector3 v20 = v[0] - v[2]; v20[2] = 0;
                Vector3 cross2p = Vector3.Cross(v2p, v20);
                if(cross2p.z * cross1p.z > 0)
                {
                    return true;
                }
            }

            return false;
        }

        Vector3 ComputeBarycentric2D(float x, float y, Triangle t)
        {
            var v = t.Positions;
            float c1 = (x * (v[1].y - v[2].y) + (v[2].x - v[1].x) * y + v[1].x * v[2].y - v[2].x * v[1].y) / (v[0].x * (v[1].y - v[2].y) + (v[2].x - v[1].x) * v[0].y + v[1].x * v[2].y - v[2].x * v[1].y);
            float c2 = (x * (v[2].y - v[0].y) + (v[0].x - v[2].x) * y + v[2].x * v[0].y - v[0].x * v[2].y) / (v[1].x * (v[2].y - v[0].y) + (v[0].x - v[2].x) * v[1].y + v[2].x * v[0].y - v[0].x * v[2].y);
            float c3 = (x * (v[0].y - v[1].y) + (v[1].x - v[0].x) * y + v[0].x * v[1].y - v[1].x * v[0].y) / (v[2].x * (v[0].y - v[1].y) + (v[1].x - v[0].x) * v[2].y + v[0].x * v[1].y - v[1].x * v[0].y);
            return new Vector3(c1, c2, c3);
        }

        public int GetIndex(int x, int y)
        {
            return y * _width + x;
        }

        public void SetPixel(Vector3 point, Color color)
        {
            if(point.x < 0 || point.x >= _width || point.y < 0 || point.y >= _height)
            {
                return;
            }

            int idx = (int)point.y * _width + (int)point.x;
            frame_buf[idx] = color;
        }

        public void UpdateFrame()
        {
H
happyfire 已提交
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
            switch (_config.DisplayBuffer)
            {
                case DisplayBufferType.Color:
                    texture.SetPixels(frame_buf);
                    break;
                case DisplayBufferType.DepthRed:
                case DisplayBufferType.DepthGray:
                    for (int i = 0; i < depth_buf.Length; ++i)
                    {
                        //depth_buf中的值范围是[0,1],且最近处为1,最远处为0。因此可视化后背景是黑色
                        float c = depth_buf[i]; 
                        if(_config.DisplayBuffer == DisplayBufferType.DepthRed)
                        {
                            temp_buf[i] = new Color(c, 0, 0);
                        }
                        else
                        {
                            temp_buf[i] = new Color(c, c, c);
                        }                        
                    }
                    texture.SetPixels(temp_buf);
                    break;
            }                                
            
H
Init  
happyfire 已提交
585
            texture.Apply();
H
happyfire 已提交
586 587 588 589 590

            if (StatDelegate != null)
            {
                StatDelegate(_verticesAll, _trianglesAll, _trianglesRendered);
            }
H
Init  
happyfire 已提交
591 592 593 594 595
        }


    }
}