【问题标题】:Rendering 2d function plot渲染二维函数图
【发布时间】:2017-08-14 13:16:18
【问题描述】:

我的任务是使用线性代数和颜色实时生成二维函数图(想象必须从函数定义中计算纯 C++ 中的图像缓冲区,例如 f(x,y) = x^2 + y^2)。输出应该是这样的3d plot。 到目前为止,我已经尝试了 3 种方法:

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.

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

谢谢。

【问题讨论】:

    标签: plot graphics geometry rendering raytracing


    【解决方案1】:

    我会选择 #3,它真的没有那么复杂,所以如果编码正确,你应该在带有纯 SW 光栅器(没有任何库)的标准机器上获得 &gt; 20 fps。我敢打赌,您正在使用一些缓慢的 API,例如 PutPixelSetPixel 或做一些疯狂的事情。如果没有看到代码或对你如何做的更好的描述,很难详细说明。您需要执行此操作的所有信息都在这里:

    还要查看每个...中的子链接...

    【讨论】:

    • 非常感谢您的回答。我熟悉射影几何。我试图对我的实现发表更清晰的描述。
    • @Gerry JAVAScript 不是我的一杯茶,但从快速查看您的代码来看,您的三角代码看起来太慢了。您对每个像素(即使未渲染)进行了太多计算,因为它基于隐式三角形方程。所以我敢打赌,这是你的主要瓶颈。比较我的链接答案中的代码。如果您不知道凸多边形填充背后的数学,请参阅那里的子链接...
    • @Gerry 更具体地说,如果我没看错,你正在做:行列式计算 + 一些向量数学和条件 + 函数子调用每个渲染三角形的 bbox 的每个像素。除非您使用可以大量并行化的专用硬件,否则这太疯狂了,而在软件渲染中则不然。为了比较,我的方法每个三角形只做 3x DDA + 由一组水平线填充的像素
    • 我还没有设法解决整个问题,但您的方法似乎要快得多。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多