2013-12-19 115 views
0

任何線索爲什麼我無法使用LWJGL創建透明紋理?我正在使用.gif圖像,因爲.PNG圖像會導致紋理出現奇怪的斑點問題。我嘗試了一些我發現的其他答案,但並沒有解決我遇到的問題。我不是OpenGL的最大成就,但我花了很多天試圖弄清楚。LWJGL透明度不起作用?


texure.java

public class Sprite { 

/** The texture that stores the image for this sprite */ 
private Texture texture; 

/** The width in pixels of this sprite */ 
private int   width; 

/** The height in pixels of this sprite */ 
private int   height; 

/** 
* Create a new sprite from a specified image. 
* 
* @param loader the texture loader to use 
* @param ref A reference to the image on which this sprite should be based 
*/ 
public Sprite(TextureLoader loader, String ref) { 
try { 
     texture = loader.getTexture(ref); 
    width = texture.getImageWidth(); 
    height = texture.getImageHeight(); 
} catch (IOException ioe) { 
    ioe.printStackTrace(); 
    System.exit(-1); 
} 
} 

/** 
* Get the width of this sprite in pixels 
* 
* @return The width of this sprite in pixels 
*/ 
public int getWidth() { 
    return texture.getImageWidth(); 
} 

/** 
* Get the height of this sprite in pixels 
* 
* @return The height of this sprite in pixels 
*/ 
public int getHeight() { 
    return texture.getImageHeight(); 
} 

/** 
* Draw the sprite at the specified location 
* 
* @param x The x location at which to draw this sprite 
* @param y The y location at which to draw this sprite 
*/ 
public void draw(int x, int y) { 
    // store the current model matrix 

    glPushMatrix(); 

    // bind to the appropriate texture for this sprite 
    texture.bind(); 

    // translate to the right location and prepare to draw 
    glTranslatef(x, y, 0); 

    // draw a quad textured to match the sprite 
    glBegin(GL_QUADS); 
    { 
     glTexCoord2f(0, 0); 
     glVertex2f(0, 0); 

     glTexCoord2f(0, texture.getHeight()); 
     glVertex2f(0, height); 

     glTexCoord2f(texture.getWidth(), texture.getHeight()); 
     glVertex2f(width, height); 

     glTexCoord2f(texture.getWidth(), 0); 
     glVertex2f(width, 0); 
    } 
    glEnd(); 

    // restore the model view matrix to prevent contamination 
    glPopMatrix(); 
} 
public void draw(int x, int y,int rotate) { 
    // store the current model matrix 
    glPushMatrix(); 

    // bind to the appropriate texture for this sprite 
    texture.bind(); 

    // translate to the right location and prepare to draw 
    //glTranslatef(x, y, 0); 
    glTranslatef(x+getWidth()/2, y+getHeight()/2, 0); // M1 - 2nd translation 
    glRotatef(rotate, 0.0f, 0.0f, 1.0f);     // M2 
    glTranslatef(-getWidth()/2, -getHeight()/2, 0); // M3 - 1st translation 
    // draw a quad textured to match the sprite 

    glBegin(GL_QUADS); 
    { 
     glTexCoord2f(0, 0); 
     glVertex2f(0, 0); 

     glTexCoord2f(0, texture.getHeight()); 
     glVertex2f(0, height); 

     glTexCoord2f(texture.getWidth(), texture.getHeight()); 
     glVertex2f(width, height); 

     glTexCoord2f(texture.getWidth(), 0); 
     glVertex2f(width, 0); 
    } 
    glEnd(); 

    // restore the model view matrix to prevent contamination 
    glPopMatrix(); 
} 

texture.java

public class Texture { 

/** The GL target type */ 
private int  target; 

/** The GL texture ID */ 
private int  textureID; 

/** The height of the image */ 
private int  height; 

/** The width of the image */ 
private int  width; 

/** The width of the texture */ 
private int  texWidth; 

/** The height of the texture */ 
private int  texHeight; 

/** The ratio of the width of the image to the texture */ 
private float widthRatio; 

/** The ratio of the height of the image to the texture */ 
private float heightRatio; 

/** 
* Create a new texture 
* 
* @param target The GL target 
* @param textureID The GL texture ID 
*/ 
public Texture(int target, int textureID) { 
    this.target = target; 
    this.textureID = textureID; 
} 

/** 
* Bind the specified GL context to a texture 
*/ 
public void bind() { 
    glBindTexture(target, textureID); 
} 

/** 
* Set the height of the image 
* 
* @param height The height of the image 
*/ 
public void setHeight(int height) { 
    this.height = height; 
    setHeight(); 
} 

/** 
* Set the width of the image 
* 
* @param width The width of the image 
*/ 
public void setWidth(int width) { 
    this.width = width; 
    setWidth(); 
} 

/** 
* Get the height of the original image 
* 
* @return The height of the original image 
*/ 
public int getImageHeight() { 
    return height; 
} 

/** 
* Get the width of the original image 
* 
* @return The width of the original image 
*/ 
public int getImageWidth() { 
    return width; 
} 

/** 
* Get the height of the physical texture 
* 
* @return The height of physical texture 
*/ 
public float getHeight() { 
    return heightRatio; 
} 

/** 
* Get the width of the physical texture 
* 
* @return The width of physical texture 
*/ 
public float getWidth() { 
    return widthRatio; 
} 

/** 
* Set the height of this texture 
* 
* @param texHeight The height of the texture 
*/ 
public void setTextureHeight(int texHeight) { 
    this.texHeight = texHeight; 
    setHeight(); 
} 

/** 
* Set the width of this texture 
* 
* @param texWidth The width of the texture 
*/ 
public void setTextureWidth(int texWidth) { 
    this.texWidth = texWidth; 
    setWidth(); 
} 

/** 
* Set the height of the texture. This will update the 
* ratio also. 
*/ 
private void setHeight() { 
    if (texHeight != 0) { 
     heightRatio = ((float) height)/texHeight; 
    } 
} 

/** 
* Set the width of the texture. This will update the 
* ratio also. 
*/ 
private void setWidth() { 
    if (texWidth != 0) { 
     widthRatio = ((float) width)/texWidth; 
    } 
} 

textureLoader.java

public class TextureLoader { 
/** The table of textures that have been loaded in this loader */ 
private HashMap<String, Texture> table = new HashMap<String, Texture>(); 

/** The colour model including alpha for the GL image */ 
private ColorModel glAlphaColorModel; 

/** The colour model for the GL image */ 
private ColorModel glColorModel; 

/** Scratch buffer for texture ID's */ 
private IntBuffer textureIDBuffer = BufferUtils.createIntBuffer(1); 

/** 
* Create a new texture loader based on the game panel 
*/ 
public TextureLoader() { 
    glAlphaColorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), 
             new int[] {8,8,8,8}, 
             true, 
             false, 
             ComponentColorModel.TRANSLUCENT, 
             DataBuffer.TYPE_BYTE); 

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

/** 
* Create a new texture ID 
* 
* @return A new texture ID 
*/ 
private int createTextureID() { 
    glGenTextures(textureIDBuffer); 
    return textureIDBuffer.get(0); 
} 

/** 
* Load a texture 
* 
* @param resourceName The location of the resource to load 
* @return The loaded texture 
* @throws IOException Indicates a failure to access the resource 
*/ 
public Texture getTexture(String resourceName) throws IOException { 
    Texture tex = table.get(resourceName); 

    if (tex != null) { 
     return tex; 
    } 

    tex = getTexture(resourceName, 
        GL_TEXTURE_2D, // target 
        GL_RGBA,  // dst pixel format 
        GL_LINEAR, // min filter (unused) 
        GL_LINEAR); 

    table.put(resourceName,tex); 

    return tex; 
} 

/** 
* Load a texture into OpenGL from a image reference on 
* disk. 
* 
* @param resourceName The location of the resource to load 
* @param target The GL target to load the texture against 
* @param dstPixelFormat The pixel format of the screen 
* @param minFilter The minimising filter 
* @param magFilter The magnification filter 
* @return The loaded texture 
* @throws IOException Indicates a failure to access the resource 
*/ 
public Texture getTexture(String resourceName, 
          int target, 
          int dstPixelFormat, 
          int minFilter, 
          int magFilter) throws IOException { 
    int srcPixelFormat; 

    // create the texture ID for this texture 
    int textureID = createTextureID(); 
    Texture texture = new Texture(target,textureID); 

    // bind this texture 
    glBindTexture(target, textureID); 

    BufferedImage bufferedImage = loadImage(resourceName); 
    texture.setWidth(bufferedImage.getWidth()); 
    texture.setHeight(bufferedImage.getHeight()); 

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

    // convert that image into a byte buffer of texture data 
    ByteBuffer textureBuffer = convertImageData(bufferedImage,texture); 

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

    // produce a texture from the byte buffer 
    glTexImage2D(target, 
        0, 
        dstPixelFormat, 
        get2Fold(bufferedImage.getWidth()), 
        get2Fold(bufferedImage.getHeight()), 
        0, 
        srcPixelFormat, 
        GL_UNSIGNED_BYTE, 
        textureBuffer); 

    return texture; 
} 

/** 
* Get the closest greater power of 2 to the fold number 
* 
* @param fold The target number 
* @return The power of 2 
*/ 
private static int get2Fold(int fold) { 
    int ret = 2; 
    while (ret < fold) { 
     ret *= 2; 
    } 
    return ret; 
} 

/** 
* Convert the buffered image to a texture 
* 
* @param bufferedImage The image to convert to a texture 
* @param texture The texture to store the data into 
* @return A buffer containing the data 
*/ 
private ByteBuffer convertImageData(BufferedImage bufferedImage,Texture texture) { 
    ByteBuffer imageBuffer; 
    WritableRaster raster; 
    BufferedImage texImage; 

    int texWidth = 2; 
    int texHeight = 2; 

    // find the closest power of 2 for the width and height 
    // of the produced texture 
    while (texWidth < bufferedImage.getWidth()) { 
     texWidth *= 2; 
    } 
    while (texHeight < bufferedImage.getHeight()) { 
     texHeight *= 2; 
    } 

    texture.setTextureHeight(texHeight); 
    texture.setTextureWidth(texWidth); 

    // create a raster that can be used by OpenGL as a source 
    // for a texture 
    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()); 
    } 

    // copy the source image into the produced image 
    Graphics g = texImage.getGraphics(); 
    g.setColor(new Color(0f,0f,0f,0f)); 
    g.fillRect(0,0,texWidth,texHeight); 
    g.drawImage(bufferedImage,0,0,null); 

    // build a byte buffer from the temporary image 
    // that be used by OpenGL to produce a texture. 
    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; 
} 

/** 
* Load a given resource as a buffered image 
* 
* @param ref The location of the resource to load 
* @return The loaded buffered image 
* @throws IOException Indicates a failure to find a resource 
*/ 
private BufferedImage loadImage(String ref) throws IOException { 
    URL url = TextureLoader.class.getClassLoader().getResource(ref); 

    if (url == null) { 
     throw new IOException("Cannot find: " + ref); 
    } 

    // due to an issue with ImageIO and mixed signed code 
    // we are now using good oldfashioned ImageIcon to load 
    // images and the paint it on top of a new BufferedImage 
    Image img = new ImageIcon(url).getImage(); 
    BufferedImage bufferedImage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); 
    Graphics g = bufferedImage.getGraphics(); 
    g.drawImage(img, 0, 0, null); 
    g.dispose(); 

    return bufferedImage; 
} 
} 
+1

你叫glEnable(GL_BLEND);和glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); – Ryxuma

+0

當我初始化OpenGL stuf或繪製項目之前,我會這麼做嗎? –

+0

當你初始化openGL – Ryxuma

回答

1

我會把這個作爲可讀性

答案您已經初始化後openGL的通話

glEnable(GL_BLEND); 
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 

這將使標準型混合

的您不必每次使用渲染通話,一次只能啓動一次

+0

謝謝你打我一秒鐘:D –

+0

@GraysonBriggs哈沒問題:) – Ryxuma