【问题标题】:Enable anti-aliasing with lwjgl使用 lwjgl 启用抗锯齿
【发布时间】:2013-09-09 16:09:12
【问题描述】:

我正在运行这个 lwjgl 应用程序:

Display.setDisplayMode(new DisplayMode(500, 500));
Display.create();

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-5, 5, -5, 5, -10, 5);
glMatrixMode(GL_MODELVIEW);

float x = 0;
while (!Display.isCloseRequested()) {
    Display.update();

    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glColor3f(1, 0, 0);
    x += 0.01f;
    glRotatef(x, x, 3 * x, 0.5f * x);
    glBegin(GL_QUADS);
    drawCube();
    glEnd();
    glLoadIdentity();
}
Display.destroy();

这基本上在窗口中绘制了一个 1x1x1 的立方体。方法drawCube()是这样的:

public void drawCube() {
    glColor3f(0.0f, 1.0f, 0.0f);          // Set The Color To Green
    glVertex3f(1.0f, 1.0f, 0f);           // Top Right Of The Quad (Top)
    glVertex3f(0f, 1.0f, 0f);             // Top Left Of The Quad (Top)
    glVertex3f(0f, 1.0f, 1.0f);           // Bottom Left Of The Quad (Top)
    glVertex3f(1.0f, 1.0f, 1.0f);         // Bottom Right Of The Quad (Top)

    glColor3f(1.0f, 0.5f, 0.0f);          // Set The Color To Orange
    glVertex3f(1.0f, 0f, 1.0f);           // Top Right Of The Quad (Bottom)
    glVertex3f(0f, 0f, 1.0f);             // Top Left Of The Quad (Bottom)
    glVertex3f(0f, 0f, 0f);               // Bottom Left Of The Quad (Bottom)
    glVertex3f(1.0f, 0f, 0f);             // Bottom Right Of The Quad (Bottom)

    glColor3f(1.0f, 0.0f, 0.0f);          // Set The Color To Red
    glVertex3f(1.0f, 1.0f, 1.0f);         // Top Right Of The Quad (Front)
    glVertex3f(0f, 1.0f, 1.0f);           // Top Left Of The Quad (Front)
    glVertex3f(0f, 0f, 1.0f);             // Bottom Left Of The Quad (Front)
    glVertex3f(1.0f, 0f, 1.0f);           // Bottom Right Of The Quad (Front)

    glColor3f(1.0f, 1.0f, 0.0f);          // Set The Color To Yellow
    glVertex3f(1.0f, 0f, 0f);             // Bottom Left Of The Quad (Back)
    glVertex3f(0f, 0f, 0f);               // Bottom Right Of The Quad (Back)
    glVertex3f(0f, 1.0f, 0f);             // Top Right Of The Quad (Back)
    glVertex3f(1.0f, 1.0f, 0f);           // Top Left Of The Quad (Back)

    glColor3f(0.0f, 0.0f, 1.0f);          // Set The Color To Blue
    glVertex3f(0f, 1.0f, 1.0f);           // Top Right Of The Quad (Left)
    glVertex3f(0f, 1.0f, 0f);             // Top Left Of The Quad (Left)
    glVertex3f(0f, 0f, 0f);               // Bottom Left Of The Quad (Left)
    glVertex3f(0f, 0f, 1.0f);             // Bottom Right Of The Quad (Left)

    glColor3f(1.0f, 0.0f, 1.0f);          // Set The Color To Violet
    glVertex3f(1.0f, 1.0f, 0f);           // Top Right Of The Quad (Right)
    glVertex3f(1.0f, 1.0f, 1.0f);         // Top Left Of The Quad (Right)
    glVertex3f(1.0f, 0f, 1.0f);           // Bottom Left Of The Quad (Right)
    glVertex3f(1.0f, 0f, 0f);             // Bottom Right Of The Quad (Right)
}

它输出这个:

对我来说,线条非常可怕,lwjgl 有抗锯齿功能吗?如果是,我该如何启用它?

【问题讨论】:

  • 据我所知,LWJGLOpenGL 没有默认的抗锯齿功能。因此,要执行抗锯齿,您可以将“世界”渲染到纹理上,然后将其渲染到相机前面的两个三角形之上。然后可以执行post processing,通过Shaders实现抗锯齿。
  • 如果您正在学习LWJGLOpenGL,那么请学习如何使用VBOs,因为glBeginglVertex等是不推荐使用的功能,不应再使用。
  • @Vallentin 感谢您对VBO 的建议,我使用的是gl* 方法,因为我发现了许多使用它们的示例。你能用一个使用纹理的例子和一个VBO的例子来回答吗?
  • 那我现在就去做! ;)

标签: java lwjgl antialiasing


【解决方案1】:

对于抗锯齿,您可以使用多重采样。要启用它,请将 PixelFormat 参数添加到 Display.create();。这是一个例子:

Display.create(new PixelFormat(/*Alpha Bits*/8, /*Depth bits*/ 8, /*Stencil bits*/ 0, /*samples*/8)); 我不确定前 3 个参数的作用 - 这些是我找到的值 here。我还看到人们使用 Display.create(new PixelFormat(8,0,0,8))。

注意:如果您将 AA 设置得太高(或其他不正确的值),它将引发 LWJGLException。

希望这会有所帮助。

PS 为迟到的答案道歉。

【讨论】:

    【解决方案2】:

    评论

    抗锯齿可以通过在帧缓冲区对象中创建多重采样帧缓冲区来实现,或者在第一次创建 LWJGL 窗口时通过默认帧缓冲区来实现。

    如果您正在学习LWJGLOpenGL,那么请学习如何使用VBOs,因为glBeginglVertex 等已从OpenGL 的核心配置文件中移除。

    VBO 示例

    这是一个 VBO 存储两个三角形的顶点和纹理坐标并渲染它的小例子!

    我假设您已经知道如何加载和绑定纹理。

    创建 VBO

    这是您创建实际顶点和纹理坐标缓冲区并将它们存储到 GPU 上的代码。

    int vertices = 6;
    
    int vertex_size = 3; // X, Y, Z,
    int texture_size = 2; // U, V,
    
    FloatBuffer vertex_data = BufferUtils.createFloatBuffer(vertices * vertex_size);
    vertex_data.put(new float[] { -1f, 1f, 0f, }); // Vertex
    vertex_data.put(new float[] { 1f, 1f, 0f, }); // Vertex
    vertex_data.put(new float[] { -1f, -1f, 0f, }); // Vertex
    
    vertex_data.put(new float[] { 1f, -1f, 0f, }); // Vertex
    vertex_data.put(new float[] { -1f, -1f, 0f, }); // Vertex
    vertex_data.put(new float[] { 1f, 1f, 0f, }); // Vertex
    
    FloatBuffer texture_data = BufferUtils.createFloatBuffer(vertices * texture_size);
    texture_data.put(new float[] { 0f, 1f, }); // Texture Coordinate
    texture_data.put(new float[] { 1f, 1f, }); // Texture Coordinate
    texture_data.put(new float[] { 0f, 0f, }); // Texture Coordinate
    
    texture_data.put(new float[] { 1f, 0f, }); // Texture Coordinate
    texture_data.put(new float[] { 0f, 0f, }); // Texture Coordinate
    texture_data.put(new float[] { 1f, 1f, }); // Texture Coordinate
    
    vertex_data.flip();
    texture_data.flip();
    
    int vbo_vertex_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
    glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    int vbo_texture_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_texture_handle);
    glBufferData(GL_ARRAY_BUFFER, texture_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    

    渲染 VBO

    那么当你要渲染VBO时,你需要做以下事情。

    texture.bind();
    
    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
    glVertexPointer(vertex_size, GL_FLOAT, 0, 0l);
    
    glBindBuffer(GL_ARRAY_BUFFER, vbo_texture_handle);
    glTexCoordPointer(texture_size, GL_FLOAT, 0, 0l);
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    glDrawArrays(GL_TRIANGLES, 0, vertices); // The vertices is of course the max vertices count, in this case 6
    
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    texture.unbind();
    

    删除 VBO

    然后,当您完成 VBO 并且不再需要它时,您可以通过执行以下操作将其删除。

    glDeleteBuffers(vbo_vertex_handle);
    glDeleteBuffers(vbo_texture_handle);
    

    LWJGL/OpenGL - 静态导入

    import static org.lwjgl.opengl.GL11.*;
    import static org.lwjgl.opengl.GL15.*;
    

    信息

    你只需要创建一次 VBO(为每一帧创建一个真的很糟糕),所以如果你使用 VBO 来存储你的地形。然后,如果发生一些变化,那么只有在那个时候你想更新 VBO,否则就保持原样。如果你用VBO做地形,而且地形真的很大,那就用自己的VBO把地形分割成不同的地形块。

    额外

    如果您有一个 Wavefront OBJ 模型,并且想要多次渲染它,那么最好的方法是将整个模型加载到一个 VBO。然后你会做一些实例化以在多个位置多次渲染它,等等。

    更新

    一个 VBO 存储三角形的顶点和颜色并渲染它的小例子!

    创建 VBO。

    这是您创建实际顶点和颜色缓冲区并将它们绑定到 VBO 的代码。

    int vertices = 3;
    
    int vertex_size = 3; // X, Y, Z,
    int color_size = 3; // R, G, B,
    
    FloatBuffer vertex_data = BufferUtils.createFloatBuffer(vertices * vertex_size);
    vertex_data.put(new float[] { -1f, -1f, 0f, });
    vertex_data.put(new float[] { 1f, -1f, 0f, });
    vertex_data.put(new float[] { 1f, 1f, 0f, });
    vertex_data.flip();
    
    FloatBuffer color_data = BufferUtils.createFloatBuffer(vertices * color_size);
    color_data.put(new float[] { 1f, 0f, 0f, });
    color_data.put(new float[] { 0f, 1f, 0f, });
    color_data.put(new float[] { 0f, 0f, 1f, });
    color_data.flip();
    
    int vbo_vertex_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
    glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    int vbo_color_handle = glGenBuffers();
    glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
    glBufferData(GL_ARRAY_BUFFER, color_data, GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    

    渲染 VBO。

    这是您需要调用的代码,用于渲染 VBO。

    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
    glVertexPointer(vertex_size, GL_FLOAT, 0, 0l);
    
    glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
    glColorPointer(color_size, GL_FLOAT, 0, 0l);
    
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);
    
    glDrawArrays(GL_TRIANGLES, 0, vertices);
    
    glDisableClientState(GL_COLOR_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
    

    用于处理/删除缓冲区的导入和代码与前面的示例相同!

    更新 2 - 完整示例

    好的,这是一个包含顶点和颜色的 VBO 的完整示例。示例是 100% 仅限 LWJGL

    当我运行以下代码时,这是我想要的结果。

    import static org.lwjgl.opengl.GL11.*;
    import static org.lwjgl.opengl.GL15.*;
    
    import java.nio.FloatBuffer;
    
    import org.lwjgl.BufferUtils;
    import org.lwjgl.input.Keyboard;
    import org.lwjgl.opengl.Display;
    import org.lwjgl.opengl.DisplayMode;
    
    public class VBOTest
    {
        public final static void main(String[] args)
        {
            int width = 1280;
            int height = 720;
    
            try
            {
                Display.setTitle("VBO Test");
                Display.setDisplayMode(new DisplayMode(width, height));
    
                Display.create();
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
    
                System.exit(0);
            }
    
            /*
             * Initialize OpenGL States
             */
    
            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();
    
            glOrtho(0f, width, height, 0f, -1f, 1f);
    
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
    
            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LEQUAL);
    
            glEnable(GL_BLEND);
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
            glEnable(GL_CULL_FACE);
            glCullFace(GL_BACK);
    
            glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    
            /*
             * Creating the Vertex & Color VBO
             */
    
            final int VERTEX_SIZE = 3; // X, Y, Z,
            final int COLOR_SIZE = 4; // R, G, B, A,
    
            int vertices = 6;
    
            int vbo_vertex_handle;
            int vbo_color_handle;
    
            FloatBuffer vertex_data = BufferUtils.createFloatBuffer(vertices * VERTEX_SIZE);
    
            float half_width = 200f;
            float half_height = 200f;
    
            vertex_data.put(new float[] { -half_width, -half_height, 0f, });
            vertex_data.put(new float[] { -half_width, half_height, 0f, });
            vertex_data.put(new float[] { half_width, -half_height, 0f, });
    
            vertex_data.put(new float[] { half_width, half_height, 0f, });
            vertex_data.put(new float[] { half_width, -half_height, 0f, });
            vertex_data.put(new float[] { -half_width, half_height, 0f, });
    
            vertex_data.flip();
    
            FloatBuffer color_data = BufferUtils.createFloatBuffer(vertices * COLOR_SIZE);
    
            color_data.put(new float[] { 1f, 0f, 0f, 1f, });
            color_data.put(new float[] { 1f, 0f, 1f, 1f, });
            color_data.put(new float[] { 1f, 1f, 0f, 1f, });
    
            color_data.put(new float[] { 0f, 1f, 0f, 1f, });
            color_data.put(new float[] { 1f, 1f, 0f, 1f, });
            color_data.put(new float[] { 1f, 0f, 1f, 1f, });
    
            color_data.flip();
    
            vbo_vertex_handle = glGenBuffers();
            glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
            glBufferData(GL_ARRAY_BUFFER, vertex_data, GL_STATIC_DRAW);
            glBindBuffer(GL_ARRAY_BUFFER, 0);
    
            vbo_color_handle = glGenBuffers();
            glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
            glBufferData(GL_ARRAY_BUFFER, color_data, GL_STATIC_DRAW);
            glBindBuffer(GL_ARRAY_BUFFER, 0);
    
            /*
             * Main Rendering Loop
             */
    
            boolean running = true;
    
            while (running)
            {
                running = (!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE));
    
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                glLoadIdentity();
    
                glPushMatrix();
                {
                    glTranslatef(width / 2f, height / 2f, 0f);
    
                    glBindBuffer(GL_ARRAY_BUFFER, vbo_vertex_handle);
                    glVertexPointer(VERTEX_SIZE, GL_FLOAT, 0, 0l);
                    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
                    glBindBuffer(GL_ARRAY_BUFFER, vbo_color_handle);
                    glColorPointer(COLOR_SIZE, GL_FLOAT, 0, 0l);
                    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
                    glEnableClientState(GL_VERTEX_ARRAY);
                    glEnableClientState(GL_COLOR_ARRAY);
    
                    glDrawArrays(GL_TRIANGLES, 0, vertices);
    
                    glDisableClientState(GL_COLOR_ARRAY);
                    glDisableClientState(GL_VERTEX_ARRAY);
                }
                glPopMatrix();
    
                glFlush();
    
                Display.sync(60);
                Display.update();
            }
    
            /*
             * Dispose Elements
             */
    
            glDeleteBuffers(vbo_vertex_handle);
            glDeleteBuffers(vbo_color_handle);
    
            Display.destroy();
    
            System.exit(0);
        }
    }
    

    【讨论】:

    • 您好,抱歉耽搁了,前两天我无法测试您的代码。如果我不想使用纹理怎么办?我想给立方体的每个面都涂上不同的颜色,可以吗?
    • 反正我用纹理测试了它,但它不起作用,我的画布总是空的
    • 嗯,那你肯定漏掉了一些东西,因为我在创建帖子之前测试了代码。虽然看看我的答案,但我已经更新了它,并添加了一个仅包含顶点和颜色的 VBO。
    • 看到你的更新,我的窗口还是空的……你能举个完整的例子吗?我真的不能让它工作。
    • 好吧,看看更新后的帖子,我刚刚添加了一个完整的 VBO 示例,其中包含顶点和颜色!
    猜你喜欢
    • 2022-08-17
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多