Java光线跟踪器:多线程CPU渲染每个线程屏幕的不同部分

Java光线跟踪器:多线程CPU渲染每个线程屏幕的不同部分,java,rendering,real-time,raytracing,Java,Rendering,Real Time,Raytracing,因此,我一直在使用纯Java开发一个简单的实时光线跟踪器,现在我已经有了从漫反射照明和镜面反射高光到光线反射和折射的大部分功能,我开始怀疑是否可以使用我的这个新引擎制作一个极简冒险游戏。唯一阻止我这样做的是在高于512x512分辨率的情况下性能不佳 所以我决定读一读Java中的多线程技术,因为我以前的项目从来都不需要多个线程,所以我以前没有这方面的经验。在那之后,我尝试了各种实现多线程渲染的方法,最终达到了4个线程分别渲染屏幕的给定部分,并将其传递给代表屏幕的缓冲图像的像素数据。我很同意这一点,

因此,我一直在使用纯Java开发一个简单的实时光线跟踪器,现在我已经有了从漫反射照明和镜面反射高光到光线反射和折射的大部分功能,我开始怀疑是否可以使用我的这个新引擎制作一个极简冒险游戏。唯一阻止我这样做的是在高于512x512分辨率的情况下性能不佳

所以我决定读一读Java中的多线程技术,因为我以前的项目从来都不需要多个线程,所以我以前没有这方面的经验。在那之后,我尝试了各种实现多线程渲染的方法,最终达到了4个线程分别渲染屏幕的给定部分,并将其传递给代表屏幕的缓冲图像的像素数据。我很同意这一点,现在唯一真正的问题是同步渲染和更新整个图像,我尝试了很多方法,但都没有找到好的方法,它总是闪烁或有一些噪音,或者是块状的,因为即使在刷新屏幕的时候,东西也一直在渲染

这是我在github中的项目源代码,渲染是在Engine.java中完成的:

我一直试图通过谷歌和stackoverflow直接寻找关于这个问题的答案,但运气不好,过去似乎没有人公开做过类似的事情,或者我只是不擅长搜索。无论如何,我已经没有主意了,我想知道这里是否有人能想出一些合理的答案,可以用来将所有渲染线程与更新位图的主线程同步

提前谢谢,我决不想被人用勺子舀,但正如我所说的,我真的没有这个想法

编辑:这是我的固定运行循环

/*
 * Main run method.
 * Handles the update and render methods.
 */
public void run() {
    for (int i = 0; i < THREAD_COUNT; i++) {
        updateDelta(i);
        lastFPS[i] = getTime();
    }
    requestFocus();
    while (running) {
        updateDelta(0);
        update(delta[0]);
        runRenderThreads();
        try {
            e.awaitTermination(10, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        render();
    }
    stop();
}
/*
*主运行方法。
*处理更新和渲染方法。
*/
公开募捐{
对于(int i=0;i

它会等待10毫秒,以使渲染线程完成其给定的任务,如果超过该时间,则只会将图像渲染到render()中的缓冲区重新开始,不在乎任务是否堆积。

光线跟踪实际上是多线程的一个主要示例,因为任务分布简单,性能要求高,所以以前肯定做过

我建议你使用。也就是说,您不直接在屏幕上绘制,而是在一个不可见的缓冲区上绘制,并为每个线程分配相同数量的像素。等待每个线程完成,然后用不可见缓冲区交换可见缓冲区,并从新图像开始。如果仍然闪烁,请尝试垂直同步

伪代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Raytracer
{
    final static int THREADS = 4;

    public static void main(String[] args) throws InterruptedException
    {
        ExecutorService renderPool = Executors.newFixedThreadPool(THREADS);
        while(true)
        {
            for(int i=0;i<THREADS;i++)
            {
                renderPool.execute(createRenderThread(i));
            }
            if(renderPool.awaitTermination(1,TimeUnit.MINUTES))
            {
                // delay here in case you want to artifically limit the frame rate  
                // v-sync if necessary here
                swapBuffers(); // should be available from your graphics library, e.g. open GL
            }
        }

    }

    private static Runnable createRenderThread(final int i)
    {
        return new Runnable()
        {
            @Override public void run()
            {
                for(int x=..;x<..;x++)
                    for(int y=..;y<..;y++)
                        render(x,y);
                // do something ...
            }
        };
    }

}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公共级光线跟踪器
{
最终静态int线程=4;
公共静态void main(字符串[]args)引发InterruptedException
{
ExecutorService renderPool=Executors.newFixedThreadPool(线程);
while(true)
{

对于(int i=0;i光线跟踪实际上是多线程的一个主要例子,因为任务分配简单,性能要求高,所以以前肯定已经做过

我建议您使用。也就是说,您不直接在屏幕上绘制,而是在一个不可见的缓冲区上绘制,并将相同数量的像素分配给每个线程。您等待每个线程完成,然后用不可见的缓冲区交换可见的像素,并从新图像开始。如果仍然出现闪烁,请尝试垂直同步

伪代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Raytracer
{
    final static int THREADS = 4;

    public static void main(String[] args) throws InterruptedException
    {
        ExecutorService renderPool = Executors.newFixedThreadPool(THREADS);
        while(true)
        {
            for(int i=0;i<THREADS;i++)
            {
                renderPool.execute(createRenderThread(i));
            }
            if(renderPool.awaitTermination(1,TimeUnit.MINUTES))
            {
                // delay here in case you want to artifically limit the frame rate  
                // v-sync if necessary here
                swapBuffers(); // should be available from your graphics library, e.g. open GL
            }
        }

    }

    private static Runnable createRenderThread(final int i)
    {
        return new Runnable()
        {
            @Override public void run()
            {
                for(int x=..;x<..;x++)
                    for(int y=..;y<..;y++)
                        render(x,y);
                // do something ...
            }
        };
    }

}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公共级光线跟踪器
{
最终静态int线程=4;
公共静态void main(字符串[]args)引发InterruptedException
{
ExecutorService renderPool=Executors.newFixedThreadPool(线程);
while(true)
{

对于(int i=0;i光线跟踪实际上是多线程的一个主要例子,因为任务分配简单,性能要求高,所以以前肯定已经做过

我建议您使用。也就是说,您不直接在屏幕上绘制,而是在一个不可见的缓冲区上绘制,并将相同数量的像素分配给每个线程。您等待每个线程完成,然后用不可见的缓冲区交换可见的像素,并从新图像开始。如果仍然出现闪烁,请尝试垂直同步

伪代码

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Raytracer
{
    final static int THREADS = 4;

    public static void main(String[] args) throws InterruptedException
    {
        ExecutorService renderPool = Executors.newFixedThreadPool(THREADS);
        while(true)
        {
            for(int i=0;i<THREADS;i++)
            {
                renderPool.execute(createRenderThread(i));
            }
            if(renderPool.awaitTermination(1,TimeUnit.MINUTES))
            {
                // delay here in case you want to artifically limit the frame rate  
                // v-sync if necessary here
                swapBuffers(); // should be available from your graphics library, e.g. open GL
            }
        }

    }

    private static Runnable createRenderThread(final int i)
    {
        return new Runnable()
        {
            @Override public void run()
            {
                for(int x=..;x<..;x++)
                    for(int y=..;y<..;y++)
                        render(x,y);
                // do something ...
            }
        };
    }

}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公共级光线跟踪器
{
最终静态int线程=4;
公共静态void main(字符串[]args)引发InterruptedException
{
ExecutorService renderPool=Executors.newFixedThreadPool(线程);
while(true)
{

对于(int i=0;i光线跟踪实际上是多线程的一个主要例子,因为任务分配简单,性能要求高,所以以前肯定已经做过

我建议您使用。也就是说,您不直接在屏幕上绘制,而是在一个不可见的缓冲区上绘制,并将相同数量的像素分配给每个线程。您等待每个线程完成,然后用invi替换可见