java - 什么是动态照明的有效实现?

标签 java lighting

我目前正在开发一款 2D Java 游戏,目前正在实现动态光照,例如手电筒、灯泡和太阳。但是,我遇到了问题。对不同实现的多次尝试尚未提供预期的结果,要么不是我想要的,要么没有按预期工作,要么滞后于整个游戏。我尝试了以下实现:

  • 使用 RadialGradientPaint 创建的 (BufferedImage) mask
  • 异步填充
  • 同步泛洪填充

事实证明,RadialGradientPaint mask 并不是我要找的东西,我对它的实现没有处理屏幕上的任何元素,这意味着光会“穿过”墙壁。

第二个实现是异步填充,没有正常工作。它只渲染了一部分光,然后就收工了,尤其是对于较大的灯。

第三个实现,一个同步的flood-fill,做了我想要的,但是因为它在主线程上运行,它卡在进程中:

用于创建最后一张图片的代码如下:

public void lightQueue(int x, int y, float level, boolean isSun){
    float newLevel;

    Queue<LightData> queue = new LinkedList<LightData>();
    queue.add(new LightData(x,y,level));

    while(!queue.isEmpty()){
        LightData d = queue.remove();

        try{
            newLevel = d.level - Level.getBlock(d.x, d.y).getLightBlockAmount();
        }catch(NullPointerException e){
            continue;
        }

        if(newLevel <= Level.getBlock(d.x, d.y).getLightLevel()) continue;

        if(newLevel > 1f){
            Level.getBlock(d.x, d.y).setLightLevel(1f);
        } else {
            Level.getBlock(d.x, d.y).setLightLevel(newLevel);
        }

        queue.add(new LightData(d.x + 1, d.y, newLevel));
        queue.add(new LightData(d.x - 1, d.y, newLevel));
        queue.add(new LightData(d.x, d.y + 1, newLevel));
        queue.add(new LightData(d.x, d.y - 1, newLevel));
    }
}
public void tick(){
    for(Emitter e:emitters){
        e.tick();
    }
    if(Main.tickCount % 20 == 0){
        for(Emitter e:emitters){
             if(e instanceof Sun){
                lightRec((int) e.getLocation().getX(), (int)e.getLocation().getY(), e.lightLevel, true);
            } else if(Level.shouldRender(e.getLocation(), Level.camera)){
                lightRec((int) e.getLocation().getX(), (int)e.getLocation().getY(), e.lightLevel, false);
            }
        }
    }
}

编辑: block 的渲染如下:

public void render(Graphics g, Camera c){
    g.drawImage(texture, c.getRelativePixelX(getLocation().getPixelX()), c.getRelativePixelY(getLocation().getPixelY()), null);
    g.setColor(new Color(0f, 0f, 0f, 1f - lightLevel));
    g.fillRect(c.getRelativePixelX(getLocation().getPixelX()), c.getRelativePixelY(getLocation().getPixelY()), getBounds(c).width, getBounds(c).height);
    g.setColor(Color.WHITE);
}

RelativePixel 只是为了正确放置而将游戏内坐标系转换为屏幕像素。

此代码每秒运行两次,以确保游戏不会立即卡住。多个光源或比 1f 亮的光源(以增加半径)将卡住游戏。

所以我的问题是,有没有更有效/更好的方法来实现动态光照? 如果没有,我有什么办法可以改进当前的系统吗?

如有不明之处请告诉我!谢谢

最佳答案

我已经以自上而下的视角回答了这个问题... ...但我是同一个问题...

使用光线追踪...

Efficient 2D Tile based lighting system

关于java - 什么是动态照明的有效实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30035815/

相关文章:

java - 在 JavaFX 中获取当前阶段的 GraphicsDevice

java - 打开 URL 的 Intent 不适用于一个应用程序,但适用于另一个应用程序

java - 正确光线追踪反射表面

c++ - OpenGL:如何使光与旋转无关?

opengl - 为什么 GL_SHININESS 的最大值是 128.0 而不是 1.0

java - 如何连接到SQS队列

java - 如何解析文本文件并从中创建数据库记录

android - 为什么这个 Android 镜面照明示例没有按预期工作?

java - 如何在C++中实现Java "Scanner"?

opengl - GLSL固定功能片段程序替换