试图渲染场景到FBO返回白色

时间:2011-09-08 06:51:13

标签: lwjgl render-to-texture fbo

所以这就是我想要做的。我正在尝试使用LWJGL进行2D游戏,LWJGL具有动态生成的地形,使用图像作为图块。它工作正常,但是当我尝试进行缩放时,瓷砖的边缘会变暗,我会在瓷砖之间得到一个额外的像素。这是缩放前后的屏幕截图:

缩放之前和之后屏幕截图:http://postimage.org/image/rhuc9744/

我看了看,从我在互联网上收集到的一点点来看,我认为要点是变焦导致像素精度问题,混合后会变得更糟。我看到一篇博客说我可以在瓷砖之间重叠一些像素,但它看起来太复杂了。我已经尝试了所有混合选项,但它们都没有奏效。所以我想,我应该将所有的瓷砖渲染成一个缓冲区,一个FBO,然后将它作为一个大的纹理应用,所以即使我缩放,我也不会看到黑暗的边缘,因为它只是一个巨大的图片。所以我已经阅读了很多关于FBO的教程,但是大多数(如果不是全部)都是针对3D的,我实际上已经开始工作了。问题是当我将它应用于2d ortho时。代码中断,我得到的只是一个白色的盒子。我已经坚持这个问题好几天了,我似乎无法使用谷歌找到答案。这是我试图开始工作的示例代码:

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(),这样你就知道我在说什么。就像我说的那样,我一直坚持这个问题,所以任何帮助都会非常感激。

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

1 个答案:

答案 0 :(得分:0)

framebufferTextureID,不应该是colourTextureID吗?