如何实施Frustum Culling? (渲染多个块时滞后)

时间:2016-06-19 06:30:59

标签: java opengl lwjgl game-engine frustum

我正在创建一个游戏,当我渲染很多块时。 fps严重下降,一切都滞后。我知道为什么它是滞后的,因为许多物体一次被渲染,但我无法弄清楚如何在我的游戏中创建和实现视锥体剔除或任何类型的剔除类。

注意:我使用的是VBO。

我无法在网上找到;请帮忙。

以下是我的一些代码:

//Render Game this were I render my game 
public void Render_GAME() {
    Update();
    if (isGameRunning == true) {
       Update();
       world.render();
       p1.Update();
       }
 }

Flat Class:我在哪里渲染块

package game.terrain.biomes;

import core.camera.*;
import core.graphics.*;
import core.math.*;
import game.blocks.*;
import game.Player;

public class Flat{

//Global Variables:
private int width;
private int height;
private int depth;

private SpaceStone[][][] blocks;

public Flat(int width, int height, int depth)
{
    this.width = width;
    this.height = height;
    this.depth = depth;

    blocks = new SpaceStone[width][height][depth];

    createBlocks();
}

//Create Blocks
private void createBlocks()
{
    SpaceStone.createBlock();

    for(int x = 0; x < width; x += 5)
    {
        for(int y = 0; y < height; y += 5)
        {
            for(int z = 0; z < depth; z += 5)
            {
                blocks[x][y][z] = new SpaceStone(new Vector3f(x, y, z), new Vector3f(0, 0, 0), new Vector3f(2.5f, 2.5f, 5f));
            }
        }
    }
}

//Render Blocks
private void renderBlocks()
{   
    Shader.BLOCK.Enable();
    SpaceStone.blocktex.bindTexture();
    SpaceStone.block.Bind();

    Shader.BLOCK.setUniform1i("tex", 1);

    Matrix4f viewMatrix = Player.getViewMatrix(Player.getCamera()); 
    Shader.BLOCK.setUniformMat4f("pr_matrix", Player.getPerspective());

    for(int i = 0; i < width; i += 5)
    {
        for(int j = 0; j < height; j += 5)
        {
            for(int k = 0; k < depth; k += 5)
            {
                Matrix4f transform = new Transformation().getTransform(blocks[i][j][k], viewMatrix);
                Shader.BLOCK.setUniformMat4f("vw_matrix", transform);
                SpaceStone.block.Draw();
            }
        }
    }

    Shader.BLOCK.Disable();
    SpaceStone.blocktex.unbindTexture();
    SpaceStone.block.Unbind();
}

//Render Flat Biome
public void renderFlatBiome()
{
    //Render Blocks
    renderBlocks();
}
}

如果您想了解更多信息,例如课程或整个项目,请发表评论并通知我。

1 个答案:

答案 0 :(得分:0)

OpenGL执行平截头体剔除,听起来你需要对每一帧进行一些处理以决定传递给OpenGL渲染哪些块(或者可能不是每一帧,每次几何体或每次都需要新的截锥体剔除计算相机变化)。您需要构造平截头体的表示并测试自己要渲染的几何体。可以将视锥体视为一个体积,因此您正在寻找该体积中包含哪些立方体。

首先要看的是哪个几何体位于近剪裁平面后面,而不是远剪裁平面。这可以通过简单地计算到近和远剪裁平面的距离并确保它们位于平面的正确一侧来完成。

接下来要做的是检查哪个几何体太靠左或向右以适应平截头体,由于性质和不同的投影,这稍微复杂一些。正交投影更容易计算,因为正投影的平截头体本身基本上是立方体。透视在形状上是梯形的(取决于视野),但原理是相同的。构造两个平面,代表平截头体的左右裁剪平面,以及剔除几何形状,这是“错误的”。与你的相机位置相关的一面。

你只是简化几何体GL来绘制GL决定不会绘制的几何体。根据场景,几何体的大小,存储在缓冲区中的方式和其他方面,绑定/解除绑定的开销和顶点处理可能很容易超过剔除客户端的任何性能损失。

我还没有编写java多年,因此无法提供源代码,但是我已经概述了执行此客户端(与OpenGL相关)的最简单形式(并且未必优化)。通过空间分组几何数据这种某种形式的层次结构(边界体积,KD树,AABB等),您可以减少剔除所需的测试量。

在很多情况下,最基本的分层分组形式是轴对齐边界框(AABB),它(如果你的立方体都没有旋转)是你使用立方体后已经拥有的。离散几何体通常使用由边界框或“平板”表示的长方体体积以某种形式分组。 (两个平行的平面,在它们之间定义一个体积)。