0

所以这就是我想要做的。我正在尝试使用 LWJGL 制作一个 2d 游戏,该游戏具有使用图像作为图块的动态生成的地形。它工作得很好,但是当我尝试进行缩放时,图块的边缘会出现深色阴影,并且我会在图块之间得到一个额外的像素。这是缩放前后的屏幕截图:

缩放前后截图: http: //postimage.org/image/rhuc9744/

我看了又看,从我在互联网上收集到的信息来看,我认为主要是缩放导致像素精度问题,在混合后会变得更糟。我看到一个博客说我可以在图块之间重叠一些像素,但这似乎太复杂了。我已经尝试了所有的混合选项,但都没有奏效。所以我想,我应该把所有的图块渲染到一个缓冲区,一个 FBO,然后将它应用为一个大纹理,所以即使我放大,我也不会看到暗边,因为它只是一张巨大的图片。所以我已经阅读了很多关于 FBO 的教程,但大多数(如果不是全部)都是针对 3D 的,而我实际上已经开始工作了。问题是当我将它应用于二维正交时。代码中断,我得到的只是一个白框。我已经被这个问题困扰了好几天了,我似乎无法使用谷歌找到答案。这里'

package com.helgravis;

import static org.lwjgl.opengl.EXTFramebufferObject.GL_COLOR_ATTACHMENT0_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.GL_FRAMEBUFFER_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.GL_RENDERBUFFER_EXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glBindFramebufferEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glBindRenderbufferEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glFramebufferRenderbufferEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glFramebufferTexture2DEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glGenFramebuffersEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glGenRenderbuffersEXT;
import static org.lwjgl.opengl.EXTFramebufferObject.glRenderbufferStorageEXT;
import static org.lwjgl.opengl.GL11.GL_INT;
import static org.lwjgl.opengl.GL11.GL_RGBA;
import static org.lwjgl.opengl.GL11.GL_RGBA8;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glBindTexture;
import static org.lwjgl.opengl.GL11.glGenTextures;
import static org.lwjgl.opengl.GL11.glTexImage2D;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.Hashtable;

import javax.swing.JPanel;

import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;


public class AnFBOExample
{
    private int width, height, canvasWidth = 800, canvasHeight = 600;
    private String title;
    private boolean bFullscreen;

    public int FRAMERATE = 60;
    public int framebufferID;                           
    public int framebufferTextureID, spriteTextureID;                               
    public int depthRenderBufferID;
    public int fboWidth = 100, fboHeight = 100; 


    public AnFBOExample()
    {
        bFullscreen = false;
    }

    public AnFBOExample(boolean bFullscreen)
    {
        this.bFullscreen = bFullscreen;
    }

    public void setTitle(String title) 
    {
        this.title = title;

        if(Display.isCreated())
            Display.setTitle(title);
    }

    public String getTitle()
    {
        return title;
    }

    public void setResolution(int x, int y) 
    {
        width = x;
        height = y;
    }

    public void setCanvasSize(int x, int y) 
    {
        canvasWidth = x;
        canvasHeight = y;
    }

    private boolean initDisplayMode() throws Exception
    {
        if(bFullscreen)
            Display.setFullscreen(true);

        try 
        {
            DisplayMode[] dm = org.lwjgl.util.Display.getAvailableDisplayModes(width, height, -1, -1, -1, -1, 60, 60);

            org.lwjgl.util.Display.setDisplayMode(dm, new String[] {
                    "width=" + width,
                    "height=" + height,
                    "freq=" + FRAMERATE,
                    "bpp="+ org.lwjgl.opengl.Display.getDisplayMode().getBitsPerPixel() 
                }
            );

            return true;
        } 
        catch(Exception e) 
        {
            e.printStackTrace();
            System.out.println("Unable to enter fullscreen, continuing in windowed mode");
        }

        return false;
    }

    public void init() throws Exception
    {
        try 
        {
            initDisplayMode();
            Display.create();

            GL11.glEnable(GL11.GL_BLEND);
            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
            GL11.glEnable(GL11.GL_ALPHA_TEST);
            GL11.glAlphaFunc(GL11.GL_GREATER, 0.5f);
            GL11.glDisable(GL11.GL_DEPTH_TEST);
            GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glLoadIdentity();
            GL11.glOrtho(0, canvasWidth, canvasHeight, 0, -1, 1);

            int framebufferID = glGenFramebuffersEXT();                         
            int colorTextureID = glGenTextures();                               
            int depthRenderBufferID = glGenRenderbuffersEXT();                  

            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID);            
            glBindTexture(GL_TEXTURE_2D, colorTextureID);                       
            GL11.glTexParameteri(GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fboWidth, fboHeight, 0, GL_RGBA, GL_INT, (java.nio.ByteBuffer) null);
            glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_TEXTURE_2D, colorTextureID, 0); 
            glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthRenderBufferID);
            glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL14.GL_DEPTH_COMPONENT24, fboWidth, fboHeight);
            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT, depthRenderBufferID); 
            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

            BufferedImage image = loadImage("resources/lamp.png");
            spriteTextureID = getTexture(image);
        }
        catch(LWJGLException le) 
        {
            le.printStackTrace();
        }
    }

    public void draw() 
    {
        glBindTexture(GL_TEXTURE_2D, 0);
        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID);

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glPushMatrix();
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, spriteTextureID);

        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2f(0, 0);
            GL11.glVertex2f(0, 0);
            GL11.glTexCoord2f(0, 1f);
            GL11.glVertex2f(0, 50f);
            GL11.glTexCoord2f(1f, 1f);
            GL11.glVertex2f(50f, 50f);
            GL11.glTexCoord2f(1f, 0);
            GL11.glVertex2f(50f, 0);
        }
        GL11.glEnd();
        GL11.glPopMatrix();

        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glPushMatrix();
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebufferTextureID);
        GL11.glTranslatef(100f, 100f, 0);
        GL11.glBegin(GL11.GL_QUADS);
        {
          GL11.glTexCoord2f(0, 0);
          GL11.glVertex2f(0, 0);
          GL11.glTexCoord2f(0, 1f);
          GL11.glVertex2f(0, 100f);
          GL11.glTexCoord2f(1f, 1f);
          GL11.glVertex2f(100f, 100f);
          GL11.glTexCoord2f(1f, 0);
          GL11.glVertex2f(100f, 0);
        }
        GL11.glEnd();
        GL11.glPopMatrix();

        Display.update();
        Display.sync(FRAMERATE);
    }

    public void draw2() 
    {
//      glBindTexture(GL_TEXTURE_2D, 0);
//      glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebufferID);
//      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glPushMatrix();
        GL11.glEnable(GL11.GL_TEXTURE_2D);
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, spriteTextureID);
        GL11.glBegin(GL11.GL_QUADS);
        {
            GL11.glTexCoord2f(0, 0);
            GL11.glVertex2f(0, 0);
            GL11.glTexCoord2f(0, 1f);
            GL11.glVertex2f(0, 50f);
            GL11.glTexCoord2f(1f, 1f);
            GL11.glVertex2f(50f, 50f);
            GL11.glTexCoord2f(1f, 0);
            GL11.glVertex2f(50f, 0);
        }
        GL11.glEnd();
        GL11.glPopMatrix();

//      glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
//      GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
//      GL11.glPushMatrix();
//      GL11.glEnable(GL11.GL_TEXTURE_2D);
//      GL11.glBindTexture(GL11.GL_TEXTURE_2D, framebufferTextureID);
//      GL11.glTranslatef(100f, 100f, 0);
//      GL11.glBegin(GL11.GL_QUADS);
//      {
//          GL11.glTexCoord2f(0, 0);
//          GL11.glVertex2f(0, 0);
//          GL11.glTexCoord2f(0, 1f);
//          GL11.glVertex2f(0, 100f);
//          GL11.glTexCoord2f(1f, 1f);
//          GL11.glVertex2f(100f, 100f);
//          GL11.glTexCoord2f(1f, 0);
//          GL11.glVertex2f(100f, 0);
//      }
//      GL11.glEnd();
//      GL11.glPopMatrix();
//      
//      Display.update();
//      Display.sync(FRAMERATE);
    }

    public void cleanup()
    {
        Display.destroy();
    }

    public void run()
    {
        while(!Thread.interrupted()) 
        {
            progress();
            handleEvents();
            draw();
            //draw2();
        }
    }

    public void handleEvents() 
    {
        while(Keyboard.next())
            if(Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) 
                quit();

        if(Display.isCloseRequested())
            quit();
    }

    public void quit()
    {
        System.exit(0);
    }

    public void progress() 
    {
        //Add game logic here
    }

    protected static boolean waitForImage(Image image, Component c) 
    {
        Image[] images = new Image[1];

        images[0] = image;

        return waitForImages(images, c);
    }

    protected static boolean waitForImages(Image[] images, Component c) 
    {
        MediaTracker tracker = new MediaTracker(c);

        for(int i=0; i<images.length; i++)
            tracker.addImage(images[i], 0);

        try 
        {
            tracker.waitForAll();
        } 
        catch(InterruptedException ie) {}

        return !tracker.isErrorAny();
    }

    public static BufferedImage loadImage(String imageFile) throws Exception 
    {
        Image image = null;

        JPanel buffer = new JPanel();

        image = buffer.getToolkit().getImage(imageFile);

        waitForImage(image, buffer);

        int width = image.getWidth(null);
        int height = image.getHeight(null);

        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = bufferedImage.createGraphics();

        g2d.drawImage(image, 0, 0, width, height, buffer);

        g2d.dispose();

        return bufferedImage;
    }

    public int getTexture(BufferedImage image) throws Exception 
    {
        return getTexture(image,
                         GL11.GL_TEXTURE_2D,
                         GL11.GL_RGBA,     
                         GL11.GL_LINEAR, 
                         GL11.GL_LINEAR);
    }

    public int getTexture(String resourceName, 
                              int target, 
                              int dstPixelFormat, 
                              int minFilter, 
                              int magFilter) throws Exception 
    { 
        BufferedImage bufferedImage = loadImage(resourceName); 
        return getTexture(bufferedImage, target, dstPixelFormat, minFilter, magFilter);
    } 

    private int createTextureID() 
    { 
        ByteBuffer temp = ByteBuffer.allocateDirect(4 * 1);
        temp.order(ByteOrder.nativeOrder());
        IntBuffer tmp = temp.asIntBuffer(); 
        GL11.glGenTextures(tmp); 
        return tmp.get(0);
    }

    public int getTexture(BufferedImage bufferedImage, 
                              int target, 
                              int dstPixelFormat, 
                              int minFilter, 
                              int magFilter) throws Exception 
    { 
        int srcPixelFormat = 0;
        int textureID = createTextureID(); 

        GL11.glBindTexture(target, textureID); 

        if(bufferedImage.getColorModel().hasAlpha()) 
            srcPixelFormat = GL11.GL_RGBA;
        else 
            srcPixelFormat = GL11.GL_RGB;

        ByteBuffer textureBuffer = convertImageData(bufferedImage); 

        if(target == GL11.GL_TEXTURE_2D) 
        { 
            GL11.glTexParameteri(target, GL11.GL_TEXTURE_MIN_FILTER, minFilter); 
            GL11.glTexParameteri(target, GL11.GL_TEXTURE_MAG_FILTER, magFilter); 
        } 

        GL11.glTexImage2D(target, 
                    0, 
                    dstPixelFormat, 
                    get2Fold(bufferedImage.getWidth()), 
                    get2Fold(bufferedImage.getHeight()), 
                    0, 
                    srcPixelFormat, 
                    GL11.GL_UNSIGNED_BYTE, 
                    textureBuffer); 

        return textureID; 
    }

    private int get2Fold(int fold) 
    {
        int ret = 2;

        while (ret < fold) 
            ret *= 2;

        return ret;
    } 

    @SuppressWarnings("rawtypes")
    private ByteBuffer convertImageData(BufferedImage bufferedImage) 
    { 
        ComponentColorModel glAlphaColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                        new int[] {8,8,8,8},
                        true,
                        false,
                        ComponentColorModel.TRANSLUCENT,
                        DataBuffer.TYPE_BYTE);

        ComponentColorModel glColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
                        new int[] {8,8,8,0},
                        false,
                        false,
                        ComponentColorModel.OPAQUE,
                        DataBuffer.TYPE_BYTE);

        ByteBuffer imageBuffer = null; 
        WritableRaster raster;
        BufferedImage texImage;

        int texWidth = 2;
        int texHeight = 2;

        while (texWidth < bufferedImage.getWidth()) 
            texWidth *= 2;

        while (texHeight < bufferedImage.getHeight()) 
            texHeight *= 2;

        if(bufferedImage.getColorModel().hasAlpha()) 
        {
            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, texWidth, texHeight, 4, null);
            texImage = new BufferedImage(glAlphaColorModel, raster, false, new Hashtable());
        } 
        else 
        {
            raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, texWidth, texHeight, 3, null);
            texImage = new BufferedImage(glColorModel, raster, false, new Hashtable());
        }

        Graphics g = texImage.getGraphics();
        g.setColor(new Color(0f,0f,0f,0f));
        g.fillRect(0,0,texWidth,texHeight);
        g.drawImage(bufferedImage,0,0,null);

        byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData(); 

        imageBuffer = ByteBuffer.allocateDirect(data.length); 
        imageBuffer.order(ByteOrder.nativeOrder()); 
        imageBuffer.put(data, 0, data.length); 
        imageBuffer.flip();

        return imageBuffer; 
    }

    public static void main(String args[]) throws Exception
    {
        AnFBOExample window = new AnFBOExample(false);

        window.setResolution(800, 600);
        window.setCanvasSize(800, 600);
        window.init();
        window.setTitle("FBO Test");
        window.run();
    }
}

该代码在 resource/lamp.png 中加载图像,该图像可以是任何 .png 文件,并尝试将其渲染到 FBO,然后将其作为 2d 四边形中的纹理应用。出于某种原因,当我尝试将 FBO 绑定为纹理时,我只会得到一个白色的空白四边形。我不确定我是否没有正确渲染到 FBO,或者我没有正确绑定它。您可以检查方法 draw() 以便您知道我在说什么。就像我说的那样,我已经被这个问题困住了一天,所以非常感谢任何帮助。

资源/lamp.png:http://s3.postimage.org/rhpdn5ms/lamp.png?noCache=1315464566

4

1 回答 1

0

framebufferTextureID,不应该是 colourTextureID 吗?

于 2012-08-14T21:54:25.547 回答