4

我目前正在从事一项需要在 JOGL 中创建游戏的任务,进展顺利,但我遇到了一个问题:

我想创建一个可以通过在游戏中按 ESC 访问的菜单功能,当按 ESC 时,显示功能需要停止显示游戏并开始显示菜单。菜单由带有一些文本覆盖的背景图像组成。

这就是我尝试实现菜单功能的方式,但我没有设法让它显示除清晰颜色之外的任何其他内容:

public class OptionsMenu 
{
    public void display(GL gl) {

        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        gl.glOrtho(0, 300, 300, 0, 0, 1);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glDisable(GL.GL_DEPTH_TEST);
        gl.glClearColor(1f, 0.5f, 0.5f, 0.5f);  
        gl.glClear(GL.GL_COLOR_BUFFER_BIT);
        gl.glBlendFunc (GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); 
        gl.glEnable (GL.GL_BLEND);
        BufferedImage bufferedImage = null;
        int w = 0;
        int h = 0;
        try {
            bufferedImage = ImageIO.read(OptionsMenu.class.getResource("menuBackground.jpg")); //The menu background
            w = ceilingPow2(bufferedImage.getWidth());
            h = ceilingPow2(bufferedImage.getHeight());
        } catch (IOException e) {
            e.printStackTrace();
        }
        WritableRaster raster = 
                Raster.createInterleavedRaster (DataBuffer.TYPE_BYTE,
                        w,
                        h,
                        4,
                        null);
        ComponentColorModel colorModel=
                new ComponentColorModel (ColorSpace.getInstance(ColorSpace.CS_sRGB),
                        new int[] {8,8,8,8},
                        true,
                        false,
                        ComponentColorModel.TRANSLUCENT,
                        DataBuffer.TYPE_BYTE);
        BufferedImage img = 
                new BufferedImage (colorModel,
                        raster,
                        false,
                        null);

        Graphics2D g = img.createGraphics();
        g.drawImage(bufferedImage, null, null);

        DataBufferByte imgBuf =
                (DataBufferByte)raster.getDataBuffer();
        byte[] imgRGBA = imgBuf.getData();
        ByteBuffer bb = ByteBuffer.wrap(imgRGBA);
        bb.position(0);
        bb.mark();

        gl.glBindTexture(GL.GL_TEXTURE_2D, 13);
        gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
        gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
        gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
        gl.glTexImage2D (GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, w, h, 0, GL.GL_RGBA, 
                GL.GL_UNSIGNED_BYTE, bb);

        gl.glEnable(GL.GL_TEXTURE_2D);
        gl.glBindTexture (GL.GL_TEXTURE_2D, 13);
        gl.glBegin (GL.GL_POLYGON);
        gl.glTexCoord2d (0, 0);
        gl.glVertex2d (0, 0);
        gl.glTexCoord2d(1,0);
        gl.glVertex2d (w, 0);
        gl.glTexCoord2d(1,1);
        gl.glVertex2d (w, h);
        gl.glTexCoord2d(0,1);
        gl.glVertex2d (0, h);
        gl.glEnd ();    
        gl.glFlush();
    }
    private static int ceilingPow2(int n) {
        int pow2 = 1;
        while (n > pow2) {
            pow2 = pow2<<1;
        }
        return pow2;
    }
}

此代码基于本教程:http ://wiki.tankaar.com/index.php?title=Displaying_an_Image_in_JOGL_(Part_1 )

我像这样调用 OptionsMenu:

    public void display(GLAutoDrawable drawable) 
    {
        GL gl = drawable.getGL();
        GLU glu = new GLU();

        if(state.equals("optionsMenu"))
        {
            if(menu == null)
                menu = new OptionsMenu;

            menu.display(gl);
        } 
        else 
        {   
            // Calculating time since last frame.
            Calendar now = Calendar.getInstance();      
            long currentTime = now.getTimeInMillis();
            int deltaTime = (int)(currentTime - previousTime);
            previousTime = currentTime;

            // Update any movement since last frame.
            updateMovement(deltaTime);
            updateCamera();

            gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
            gl.glLoadIdentity();
            glu.gluLookAt( camera.getLocationX(), camera.getLocationY(), camera.getLocationZ(), 
                    camera.getVrpX(), camera.getVrpY(), camera.getVrpZ(),
                    camera.getVuvX(), camera.getVuvY(), camera.getVuvZ() );

            // Display all the visible objects of MazeRunner.
            for( Iterator<VisibleObject> it = visibleObjects.iterator(); it.hasNext(); ) {
                it.next().display(gl);
            }

            gl.glLoadIdentity();
            gl.glFlush();
        }
    }

它不会抛出任何错误,只是不会显示图像。但是它确实显示了清晰的颜色 gl.glClearColor(1f, 0.5f, 0.5f, 0.5f); 在 OptionsMenu 的显示函数中定义

我很困惑,我不知道我将如何解决这个问题。

对不起,很长的帖子,但如果有人能帮助我,我会非常感激。

4

1 回答 1

0

我想清除颜色缓冲区gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT ); 应该放在 OptionsMenu 的显示方法的开头。

我有一些建议,例如上面发布的代码:

  • 更改范围GLU glu = new GLU();,因为glu每次调用 opengl 显示回调方法时都会分配。
  • 还要移到gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);if 语句之前,不要使用每个对象的显示方法(例如 OptionsMenu.display())。试着保持单身。
  • 使用 TextureIO 上传纹理,如果可能的话,只需上传一次,然后在您的显示方法中使用该纹理。纹理加载过程有很大的开销。
于 2015-02-11T12:34:38.470 回答