java - 简单的 JOGL 游戏在 gtx 470 上运行非常缓慢

标签 java opengl jogl

我一直在为我的计算机科学课制作游戏。为简单起见,我一直在制作一组迷你游戏。为了好玩,我尝试制作了经典贪吃蛇游戏的 3d 版本。物理和碰撞检测工作正常,并且在学校计算机(中等质量的 mac)上游戏运行非常流畅。但是,在我的家用计算机上,它以 8 fps 的速度运行。我的家庭计算机在配备最新驱动程序的 gtx 470 上运行,程序中的查询确认代码在配备 opengl 4.2 的 gtx 470 上运行。

这是渲染代码(在 GLCanvas 中运行)

 GL2 gl = ( drawable.getGL()).getGL2();
     /*System.out.println(gl.glGetString(GL.GL_VENDOR)+"\n"+
                gl.glGetString(GL.GL_RENDERER)+"\n"+
                gl.glGetString(GL.GL_VERSION));*/

     gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
    //Init camera
    gl.glMatrixMode(GL2.GL_PROJECTION);
    gl.glLoadIdentity();

    // Perspective.
    float widthHeightRatio = (float) getWidth() / (float) getHeight();
    glu.gluPerspective(75, widthHeightRatio, 1, 2000);

    double dX, dY, dZ;
    if (player.locs.size()==0)
    {
        dX=0.1*player.vel.x;
        dY=0.1*player.vel.y;
        dZ=0.1*player.vel.z;
    }
    else
    {
        dX=player.xHead-player.locs.get(0).x;
        dY=player.yHead-player.locs.get(0).y;
        dZ=player.zHead-player.locs.get(0).z;

    }
    player.up.normalizeDist();
    double xPos=4*dX-0.1*player.up.x;
    double yPos=4*dY-0.1*player.up.y;
    double zPos=4*dZ-0.1*player.up.z;
    double desiredDist=0.2;
    double totalDist=Math.sqrt(xPos*xPos+yPos*yPos+zPos*zPos);
    xPos=xPos*desiredDist/totalDist;
    yPos=yPos*desiredDist/totalDist;
    zPos=zPos*desiredDist/totalDist;
    double camX=player.xHead-xPos;
    double camY=player.yHead-yPos;
    double camZ=player.zHead-zPos;
    glu.gluLookAt(xWidth*(camX), yWidth*(camY),zWidth*(camZ), xWidth*(player.xHead+2*dX), yWidth*(player.yHead+2*dY), zWidth*(player.zHead+2*dZ), player.up.x, player.up.y, -player.up.z);
    // Change back to model view matrix.
    gl.glMatrixMode(GL2.GL_MODELVIEW);
    gl.glLoadIdentity();


    float SHINE_ALL_DIRECTIONS = 1;
    float[] lightPos = {xWidth/2, yWidth/2, zWidth/2, SHINE_ALL_DIRECTIONS};
    float[] lightColorAmbient = {0.2f, 0.2f, 0.2f, 0.2f};
    float[] lightColorSpecular = {0.8f, 0.8f, 0.8f, 0.8f};

    // Set light parameters.
    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, lightPos, 0);
    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_AMBIENT, lightColorAmbient, 0);
    gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_SPECULAR, lightColorSpecular, 0);

    // Enable lighting in GL.

    gl.glEnable(GL2.GL_LIGHT1);
    gl.glEnable(GL2.GL_LIGHTING);


    // Set material properties.
    float[] rgba = {1f, 1f, 1f};
    gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
    gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
    gl.glMaterialf(GL2.GL_FRONT, GL2.GL_SHININESS, 0.5f);
    /*gl.glMaterialfv(GL.GL_BACK, GL.GL_AMBIENT, rgba, 0);
    gl.glMaterialfv(GL.GL_BACK, GL.GL_SPECULAR, rgba, 0);
    gl.glMaterialf(GL.GL_BACK, GL.GL_SHININESS, 0.5f);*/


   // gl.glColor3f(1f,1f,1f);
    if (camX>0)
    {

        gl.glBegin(GL2.GL_POLYGON);
        gl.glNormal3d(1,0,0);
        gl.glVertex3d(0, 0, 0);
        gl.glVertex3d(0, 0, zWidth);
        gl.glVertex3d(0, yWidth, zWidth);
        gl.glVertex3d(0, yWidth, 0);
        gl.glEnd();
    }
    if (camY>0)
    {
        gl.glBegin(GL2.GL_POLYGON);
        gl.glNormal3d(0, 1, 0);
        gl.glVertex3d(0, 0, 0);
        gl.glVertex3d(0, 0, zWidth);
        gl.glVertex3d(xWidth, 0, zWidth);
        gl.glVertex3d(xWidth, 0, 0);
        gl.glEnd();
    }
    if (camZ>0)
    {
        gl.glBegin(GL2.GL_POLYGON);
        gl.glNormal3d(0, 0, 1);
        gl.glVertex3d(0, 0, 0);
        gl.glVertex3d(xWidth, 0, 0);
        gl.glVertex3d(xWidth, yWidth, 0);
        gl.glVertex3d(0, yWidth, 0);
        gl.glEnd();
    }
    if (camX<1)
    {
        gl.glBegin(GL2.GL_POLYGON);
        gl.glNormal3d(-1, 0, 0);
        gl.glVertex3d(xWidth, 0, 0);
        gl.glVertex3d(xWidth, 0, zWidth);
        gl.glVertex3d(xWidth, yWidth, zWidth);
        gl.glVertex3d(xWidth, yWidth, 0);
        gl.glEnd();
    }
    if (camY<1)
    {
        gl.glBegin(GL2.GL_POLYGON);
        gl.glNormal3d(0, -1, 0);
        gl.glVertex3d(0, yWidth, 0);
        gl.glVertex3d(0, yWidth, zWidth);
        gl.glVertex3d(xWidth, yWidth, zWidth);
        gl.glVertex3d(xWidth, yWidth, 0);
        gl.glEnd();
    }
    if (camZ<1)
    {

        gl.glBegin(GL2.GL_POLYGON);
        gl.glNormal3d(0, 0, 1);
        gl.glVertex3d(0, 0, zWidth);
        gl.glVertex3d(xWidth, 0, zWidth);
        gl.glVertex3d(xWidth, yWidth, zWidth);
        gl.glVertex3d(0, yWidth, zWidth);
        gl.glEnd();
    }


    player.draw(xWidth, yWidth, zWidth, drawable, glu);
    for (int i=0; i<bullets.size(); i++)
    {
        bullets.get(i).draw(drawable, glu, xWidth, yWidth, zWidth);
    }
    for (int i=0; i<basicEntities.size(); i++)
    {
        basicEntities.get(i).draw( xWidth, yWidth, zWidth, drawable, glu);
    }

然后大量复制粘贴调用代码如下:(xHead、yHead 和 zHead 是坐标)

GL gl=drawable.getGL();
GL2 gl2=gl.getGL2();        
        gl2.glPushMatrix();
        gl2.glTranslated(xHead*xWidth, yHead*yWidth, zHead*zWidth);
        float[] rgba = {0.3f, 0.5f, 1f};
        gl2.glMaterialfv(GL.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl2.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl2.glMaterialf(GL.GL_FRONT, GL2.GL_SHININESS, 0.5f);
        GLUquadric head = glu.gluNewQuadric();
        glu.gluQuadricDrawStyle(head, GLU.GLU_FILL);
        glu.gluQuadricNormals(head, GLU.GLU_FLAT);
        glu.gluQuadricOrientation(head, GLU.GLU_OUTSIDE);
        final float radius = (float) (dotSize*xWidth);
        final int slices = 32;
        final int stacks = 32;
        glu.gluSphere(head, radius, slices, stacks);
        glu.gluDeleteQuadric(head);
        gl2.glPopMatrix();

编辑:我可以通过减少二次曲面中切片和堆栈的数量来让游戏运行得更快,但这会使游戏变得相当丑陋。 此外,我删除了 a.add(this) (来自动画师)并且游戏仍在运行。我是否为所有内容设置了两次动画?虽然它仍然很慢。

最佳答案

我无法完全解释为什么它在您学校的计算机上运行得那么好,但是您使用 OpenGL 的方式是一种古老的方式并且对性能来说很糟糕。

使用 glBegin 绘制总是非常昂贵,因为它必须将每个顶点作为单独的 API 调用发送,这对性能不利。您应该改为使用顶点数组(好的)或顶点缓冲区对象(在大多数情况下更好)进行渲染。使用这些需要稍作转变,但我相信您可以使用这些搜索词找到很多教程。

我也不是 glu 功能方面的专家,尽管您对 gluSphere 和 gluQuadrics 的使用也让我怀疑。 glu 函数的大部分工作可能不会在显卡上执行,因此每次调用 gluSphere 时,CPU 都必须重新计算球体的所有顶点,然后才能对 GPU 执行任何操作。更好的解决方案是生成您自己的球体顶点列表,将其作为 VBO 上传到 GPU,然后在您想要绘制球体时随时执行 VBO 绘制调用。这应该可以节省大量的计算时间。

关于java - 简单的 JOGL 游戏在 gtx 470 上运行非常缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10971121/

相关文章:

java - 将 Java 字符串中的撇号替换为 "\' "

java - 地形在水中闪烁|深度缓冲区精度问题?

java - 如何与 Maven 安装并行运行 Maven 测试?

java - 将数据从 servlet 发送到 applet : How can I implement this?

由 C++ OpenGL 重复

java - LWJGL:打开窗口导致程序崩溃

OpenGL 碰撞检测

java - glReadPixels() 返回零数组

performance - 10,000 个静态立方体的 OpenGL 性能

java - 如何跨 Web 应用程序共享 Hibernate SessionFactory?