2017-03-22 78 views
1

我的任务是使用除线性代数和颜色之外的任何东西来实时生成二维函数的图(想象必须从函数定义中以普通C++计算图像缓冲区,例如f( x,y)= x^2 + y^2)。输出应该是这样的3d plot。 到目前为止我曾尝试的方法3:渲染2d函数图

1:光线追踪:

鸿沟第(x,y)平面成三角形,找到每个顶点的Z值,从而划分积成三角形。将每条光线与三角形相交。

2:球体跟踪:

的方法用于渲染隐式曲面描述here

3:光栅化:

的倒数(1)。将绘图分解为三角形,将它们投影到相机平面上,循环遍布画布的像素,并为每个像素选择“最近”的投影像素。

所有这些都是缓慢的方式。我的一部分任务是在相机周围移动,所以剧情必须在每一帧中重新渲染。请指向另一个信息来源/另一种算法/任何形式的帮助。谢谢。

编辑

正如指出的那样,这里是我的非常基本的光栅化的伪代码。我知道这个代码可能并不完美,但它应该类似于一般的想法。然而,当我的情节分裂成200个三角形(我认为它不够)时,它已经非常缓慢地运行,即使没有渲染任何东西。我甚至没有使用深度缓冲区的可见性。我只是想通过建立帧缓冲器如下来测试速度:

:在JavaScript框架我使用,_表示阵列索引和a..b构成的列表从a到b。

/* 
* Raster setup. 
* The raster is a pxH x pxW array. 
* Raster coordinates might be negative or larger than the array dimensions. 
* When rendering (i.e. filling the array) positions outside the visible raster will not be filled (i.e. colored). 
*/ 

pxW := Width of the screen in pixels. 
pxH := Height of the screen in pixels. 
T := Transformation matrix of homogeneous world points to raster space. 

// Buffer setup. 
colBuffer = apply(1..pxW, apply(1..pxH, 0)); // pxH x pxW array of black pixels. 

// Positive/0 if the point is on the right side of the line (V1,V2)/exactly on the line. 
// p2D := point to test. 
// V1, V2 := two vertices of the triangle. 
edgeFunction(p2D, V1, V2) := (
    det([p2D-V1, V2-V1]); 
); 

fillBuffer(V0, V1, V2) := (
    // Dehomogenize. 
    hV0 = V0/(V0_3); 
    hV1 = V1/(V1_3); 
    hV2 = V2/(V2_3); 
    // Find boundaries of the triangle in raster space. 
    xMin = min(hV0.x, hV1.x, hV2.x); 
    xMax = max(hV0.x, hV1.x, hV2.x); 
    yMin = min(hV0.y, hV1.y, hV2.y); 
    yMax = max(hV0.y, hV1.y, hV2.y); 
    xMin = floor(if(xMin >= 0, xMin, 0)); 
    xMax = ceil(if(xMax < pxW, xMax, pxW)); 
    yMin = floor(if(yMin >= 0, yMin, 0)); 
    yMax = ceil(if(yMax < pxH, yMax, pxH)); 
    // Check for all points "close to" the triangle in raster space whether they lie inside it. 
    forall(xMin..xMax, x, forall(yMin..yMax, y, (
    p2D = (x,y); 
    i = edgeFunction(p2D, hV0.xy, hV1.xy) * edgeFunction(p2D, hV1.xy, hV2.xy) * edgeFunction(p2D, hV2.xy, hV0.xy); 
    if (i > 0, colBuffer_y_x = 1); // Fill all points inside the triangle with some placeholder. 
))); 
); 

mapTrianglesToScreen() := (
    tvRaster = homogVerts * T; // Triangle vertices in raster space. 
    forall(1..(length(tvRaster)/3), i, (
    actualI = i/3 + 1; 
    fillBuffer(tvRaster_actualI, tvRaster_(actualI + 1), tvRaster_(actualI + 2)); 
)); 
); 

// After all this, render the colBuffer. 

这种方法有什么问题?为什么这么慢?

谢谢。

回答

4

我会去与#3它真的没有那么复杂,所以你应该得到一个标准的机器上> 20 fps的纯SW光栅(没有任何库),如果编码正确。我敢打赌,你正在使用一些缓慢的APIPutPixelSetPixel或做一些疯狂的事情。没有看到代码或更好地描述你如何做,这是很难阐述。所有你需要做的这个信息是在这里:

确实也看在每个子链接...

+0

谢谢你非常喜欢你的答案。我熟悉投影几何。我试图发布一个更清晰的描述我的实现。 – Gerry

+0

@Gerry JAVAScript不是我的一杯茶,但是从快速查看您的代码,您的三角形代码看起来太慢了。你每个像素做了太多的计算(即使没有渲染),因为它基于隐式三角方程。所以我敢打赌,这是你的主要瓶颈。比较我的链接答案的代码。如果你不知道凸多边形填充背后的数学,请参阅其中的子链接... – Spektre

+0

@Gerry更具体一点,如果我看到它正确,你正在做:行列式计算+某些向量数学和条件+函数子调用每个渲染三角形的bbox的每个像素。这是疯狂的,除非你在专用的硬件上,它可以大量并行化,这在SW渲染中不是这种情况。比较而言,我的方法每个三角形只需要3倍的DDA +通过一组水平线填充像素 – Spektre