开发者

Trying To Render Scene To FBO Returns White

开发者 https://www.devze.com 2023-04-03 22:41 出处:网络
So this is what I\'m trying to do. I\'m trying to make a 2d game using LWJGL that has a dynamically generated terrain using images as tiles. It works fine, but when I try to do a zoom, the tiles get a

So this is what I'm trying to do. I'm trying to make a 2d game using LWJGL that has a dynamically generated terrain using images as tiles. It works fine, but when I try to do a zoom, the tiles get a dark shade on the edges and I get an extra pixel in-between tiles. Here's a screenshot of before and after zoom:

Before and After Zoom Screenshot: http://postimage.org/image/rhuc9744/

I've looked and looked, and from what little I've gathered on the internet, I think the gist is that zoom is causing pixel-precision issues which gets worse after blending. I saw a blog saying I can overlap some pixels between tiles, but it seems too complicated. I've tried all blending options, and none of them worked. So I figured, I should just render all the tiles into a buffer, an FBO, and then apply it as one big texture, so even when I zoom, I won't see dark edges because it would all be just one giant picture. So I've read a lot of tutorials on FBO, but most if not all of them are meant for 3D, which I actually got working. The problem is when I apply it to 2d ortho. The code breaks and all I get is a white box. I've been stuck on this problem for days, and I can't seem to find an answer using google. Here's a sample code I'm t trying to get working:

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();
    }
}

The code loads an image in resource/lamp.png, which can be any .png file, and tries to render it to an FBO, then applies it as a texture in a 2d quad. For some reason, I only get a white blank quad when I try to bind the FBO as a texture. I'm not sure if I'm not rendering to the FBO properly, or I'm not binding it correctly. You can check the method draw() so you know what I'm talking about. Like I said, I've been stuck in this problem for day, so any help would be very much appreciated.

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


framebufferTextureID, shouldn't it be colourTextureID?

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号