我的任務是使用除線性代數和顏色之外的任何東西來實時生成二維函數的圖(想象必須從函數定義中以普通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.
這種方法有什麼問題?爲什麼這麼慢?
謝謝。
謝謝你非常喜歡你的答案。我熟悉投影幾何。我試圖發佈一個更清晰的描述我的實現。 – Gerry
@Gerry JAVAScript不是我的一杯茶,但是從快速查看您的代碼,您的三角形代碼看起來太慢了。你每個像素做了太多的計算(即使沒有渲染),因爲它基於隱式三角方程。所以我敢打賭,這是你的主要瓶頸。比較我的鏈接答案的代碼。如果你不知道凸多邊形填充背後的數學,請參閱其中的子鏈接... – Spektre
@Gerry更具體一點,如果我看到它正確,你正在做:行列式計算+某些向量數學和條件+函數子調用每個渲染三角形的bbox的每個像素。這是瘋狂的,除非你在專用的硬件上,它可以大量並行化,這在SW渲染中不是這種情況。比較而言,我的方法每個三角形只需要3倍的DDA +通過一組水平線填充像素 – Spektre