2011-09-08 69 views
0

所以这就是我想要做的。我正在尝试使用LWJGL制作2D游戏,该游戏具有动态生成的地形,并使用图像作为贴图。它工作正常,但是当我尝试进行缩放时,瓷砖的边缘会产生阴影,我会在瓷砖之间获得额外的像素。下面是之前和变焦之后的截图:试图渲染场景FBO返回白色

之前和放大截图后:http://postimage.org/image/rhuc9744/

我看了又看,并从一点点我收集的互联网上,我认为要点在于放大导致混合后像素精度问题变得更糟。我看到一个博客说我可以在瓷砖之间重叠一些像素,但看起来太复杂了。我试过所有的混合选项,但都没有工作。所以我想,我应该把所有的瓷砖都放到一个缓冲区,一个FBO中,然后把它作为一个大纹理应用,所以即使当我放大时,我也不会看到黑边,因为它们都只是一个巨大的图片。所以我已经阅读了很多关于FBO的教程,但是大多数如果不是全部都是用于3D的,我实际上已经开始工作了。问题是当我将它应用到2d ortho。代码打破了,我得到的只是一个白盒子。我被困在这个问题上好几天了,我似乎无法用google找到答案。下面是我牛逼试图让工作示例代码:

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

的代码加载资源/ lamp.png的图像,它可以是任何PNG文件,并尝试将其渲染到FBO,然后将其用作2d四元组中的纹理。出于某种原因,当我尝试将FBO作为纹理进行绑定时,我只得到一个白色的空白四边形。我不确定我是不是正确渲染FBO,或者我没有正确地绑定它。你可以检查draw()方法,这样你就知道我在说什么了。就像我说的,我一直在这个问题上停留一天,所以任何帮助将非常感激。

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

+0

你能渲染一种白色以外的颜色吗? – RobotRock

回答

0

framebufferTextureID,应该不是被colourTextureID?