我正在使用OpenTK在C#中编写一个简单的raycaster。 我希望我的视图每秒刷新60次,所以我有一个计时器调用我的Render()函数,它在屏幕上显示一个纹理。
我想使用递归函数通过将场景划分为更小的矩形并渲染每个场景直到矩形大小为1px来渲染场景。我的递归将像素颜色写入字节数组,我需要转换为纹理。递归非常慢,所以每当我的场景发生变化时,我都想在背景线程中运行它。
同步线程的正确方法是什么,以便一个写入纹理数组(大约需要一秒钟),但另一个线程每1/60秒读一次并在屏幕上打印?
byte[, ,] texture;
递归:
public void RenderAdaptively(int top, int left, int width, int height)
{
Color color = getColor(top, left);
for (int i = top; i < top + width + 1; i++)
{
for (int j = left; j < left + height; j++)
{
texture[i, j, 0] = color.R;
texture[i, j, 1] = color.G;
texture[i, j, 2] = color.B;
}
}
int halfw = width / 2;
int halfh = height / 2;
int newwidth = width - halfw;
int newheight = height - halfh;
if (width > 1 && height > 1)
{
RenderAdaptively(top, left, halfw, halfh, false);
RenderAdaptively(top + halfw, left + halfh, newwidth, newheight, false);
RenderAdaptively(top, left + halfh, halfw, newheight, false);
RenderAdaptively(top + halfw, left, newwidth, halfh, false);
}
}
在另一个帖子中:
raycasting_texture = TexUtil.CreateRGBTexture(width, height, texture);
答案 0 :(得分:1)
您可以尝试多种选择,但我会这样做:
有两个缓冲区用于将纹理存储为字节数组,例如0
和1
,
在一个缓冲区中进行纹理计算,
完成后,通过将volatile int updated_buffer
设置为更新的缓冲区索引来发出信号。
让其他线程定期读取updated_buffer
,并保留其最新值的副本。当该副本与int不同步时,更新副本并将纹理上传到内存,
请注意,此解决方案依赖于以下几个方面:
只有两个线程处理字节数组缓冲区,
updated_buffer
仅由(纹理)使用者线程读取并由生产者线程编写,
最重要的是,纹理上传比计算更明智
如果#2或#3被破坏,则必须在纹理缓冲区(如互斥锁)上使用更严格的同步方法,以确保纹理缓冲区在上载时不会被覆盖。
最后,您的递归计算可以通过移动到某个阈值(例如8 * 8像素块)以下的迭代来获得轻微提升,而不是一直下降到1px。事实上,迭代地完成所有操作应该更快(如果在单个核心上的单个线程中完成),尽管它在很大程度上依赖于计算像素的算法。