PNG Textures

Hello,

in the other this has been mentioned before but I still have the same problem … so I though might be easier to make tpoic about it.

I make my textures with photoshop with transparant parts and then save it as a PNG.

my loader is as follows:


/**
             * @param gl
             * @param i
             * @param string
             */
      private void loadLinearGLTextures(GL gl, int textureID, String textureName)
            throws IOException {

            int[] temp = new int[1]; // create blank 
            gl.glGenTextures(1, temp); // fill with proper gl texture id 
            texturesID[textureID] = temp[0];

            // store gl texture id in correct slot of global array.
            TextureReader.Texture texture = TextureReader.readTexture(textureName);

            //Create Linear Filtered Texture
            gl.glBindTexture(GL.GL_TEXTURE_2D, texturesID[textureID]);
            gl.glTexParameteri(
                  GL.GL_TEXTURE_2D,
                  GL.GL_TEXTURE_MAG_FILTER,
                  GL.GL_LINEAR);
            gl.glTexParameteri(
                  GL.GL_TEXTURE_2D,
                  GL.GL_TEXTURE_MIN_FILTER,
                  GL.GL_LINEAR);

            gl.glTexImage2D(
                  GL.GL_TEXTURE_2D,
                  0,
                  3,
                  texture.getWidth(),
                  texture.getHeight(),
                  0,
                  GL.GL_RGB,
                  GL.GL_UNSIGNED_BYTE,
                  texture.getPixels());

      }

and I presume there aren’t any problems with this …

to draw the image then I use this code:


/** Draw a picture */
      private void drawPicture(GL gl, int x,int y, int tID) {
            gl.glEnable(GL.GL_BLEND);
            gl.glDisable(GL.GL_DEPTH_TEST);
            
            gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ZERO);
            
            // Bind the mask texture to our new 2D quad
            gl.glBindTexture(GL.GL_TEXTURE_2D, texturesID[tID]);
            gl.glBegin(GL.GL_QUADS);
            gl.glTexCoord2f(0, 0);
            gl.glVertex2i(0, 0);
            gl.glTexCoord2f(1, 0);
            gl.glVertex2i(x, 0);
            gl.glTexCoord2f(1, 1);
            gl.glVertex2i(x, y);
            gl.glTexCoord2f(0, 1);
            gl.glVertex2i(0, y);
            gl.glEnd();

            gl.glDisable(GL.GL_BLEND);
            gl.glEnable(GL.GL_DEPTH_TEST);
      }

and I think the problem is with the blendfuction or so, but I already tried a few methods but now satisfied. The best one so far was gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_ZERO); but then the transparant parts are transparent but the rest of the image is very dark and semi transparant … pls someone … ?

[quote]H
and I think the problem is with the blendfuction or so, but I already tried a few methods but now satisfied. The best one so far was gl.glBlendFunc(GL.GL_DST_COLOR, GL.GL_ZERO);
[/quote]
While the documentation for GL is usually pretty good, the bits on blending are just painful to read :o It took me a while to figure out how glBlendFunc worked.

I’m assuming that PS is saving your transparency in the alpha channel in the png, which is a good way to do things. However you’re loading the texture as RGB, not RGBA so you don’t have the alpha channel in your texture. To use this you’ll need to change to RGBA in glTexImage2D and probably change your TextureReader.readTexture so that texture.getPixels returns the 4 channel data, not three channel.

After that you should be able to use GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA to blend correctly.

yip … sorry seams like I posted the wrong loaders and stuff here, cause I already tried it that way, with changing the textureLoader with true to read the aplhachannel, adn with the RGBA parameter for glTexImage2D … but I presume then that I am doing something wrong in PhotoShop. I simply make my picture with a transparant background and then save it as a .png … do I need to do something special to add the alpha channel or so … ?

I have no idea how PS handles transparency/alpha, its difficult enough at time to get PSP to work correctly with RGBA images. :o Looks like the best idea would be to post the entire app with texture if thats possible…?

oké … no problemo … here we go …


/*
 * Created on 7-okt-2003
 */
package menu;

import net.java.games.jogl.*;

import java.awt.*;
import javax.vecmath.*;
import java.io.*;
import glUtil.*;

/**
 * A textbox for text of main characters with picture
 * and name. Will take care of all visualization aspects.
 * 
 * @author Kozen
 */
public class PictureTextDisplayer implements TextDisplayer {

      /** Name of the object for the picture */
      private String name;

      /** Dimension of this box */
      private Dimension dimension;

      /** Location on screen */
      private Point location;

      /** Displayed text so far */
      private String currentText;

      /** Complete text to display */
      private String completeText;

      /** Current character location */
      private int charLocation;

      /** Color for name displaying */
      private float[] nameColor;

      /** Color for text displaying */
      private float[] textColor;

      /** Are we finished writing and waiting keypress ? */
      private boolean finished;

      /** Are we visible .. */
      private boolean active;

      // ------------------------------------------------------
      //       For Texturing:
      // ------------------------------------------------------

      /** Array of textureID's */
      private int[] texturesID = new int[4];

      /** Base for the font texture */
      private int base;

      /** Font Texture ID */
      public static int FONT_TEXTURE_ID = 0;
      /** Person icon ID */
      public static int ICON_ID = 1;
      /** Background picture for text ID */
      public static int BACKGROUND_ID = 2;
      /** Continue text icon ID */
      public static int CONTINUE_TEXT_ID = 3;

      /**
       * Basic Contructor which creates the textdipslayer with
       * with only name as paramater. Rest is standard.
       * 
       * @param name Name if this character
       */
      public PictureTextDisplayer(String name) {

            this.name = name;

            finished = false;
            active = true;
            currentText = "\"";
            charLocation = 0;
            completeText = "Dit is een Test. \n Welcome to XonoX! \n ... ";

            location = new Point(300, 20);

            Color3f tmpColor = new Color3f(new Color(204, 213, 192));
            nameColor = new float[] { tmpColor.x, tmpColor.y, tmpColor.z };

            tmpColor = new Color3f(new Color(205, 236, 161));
            textColor = new float[] { tmpColor.x, tmpColor.y, tmpColor.z };
      }

      /** @see overlay.TextDisplayer#getDisplayType() */
      public int getDisplayType() {
            return PICTURE_TEXT_DISPLAYER;
      }

      /** 
       * Draw the current box with already visible text,
       * name and icon
       */
      public void display(GLDrawable drawable) {
            GL gl = drawable.getGL();

            // easier use:
            int x = location.x;
            int y = location.y;

            gl.glLoadIdentity();
            gl.glTranslatef(x, y, 0);

            // draw background
            drawPicture(gl, 256, 128, BACKGROUND_ID);

            // draw name:
            gl.glColor3fv(nameColor);
            glPrint(gl, x + 10, y + 77, name, 0, 1.00f);

            // draw text:
            gl.glColor3fv(textColor);
            String[] lines = currentText.split("\n");
            for (int i = 0; i < lines.length; i++) {
                  glPrint(gl, x + 10, y + 56 - i * 15, lines[i], 0, 1.00f);
            }

            // finished = true;

            // awaiting press ?
            if (finished) {
                  gl.glTranslatef(230, 8, 0);
                  drawPicture(gl, 16, 16, CONTINUE_TEXT_ID);
                  // gl.glTranslatef(-(x+145),-(y+20),0);      
            }

            // draw the character icon:
            gl.glTranslatef(165, 94, 0);
            // drawPicture(gl,128,ICON_ID,ICON_MASK_ID);
      }

      /** Draw a picture */
      private void drawPicture(GL gl, int x, int y, int tID) {
            gl.glEnable(GL.GL_BLEND);
            gl.glDisable(GL.GL_DEPTH_TEST);

            gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA );

            // Bind the mask texture to our new 2D quad
            gl.glBindTexture(GL.GL_TEXTURE_2D, texturesID[tID]);
            gl.glBegin(GL.GL_QUADS);
            gl.glTexCoord2f(0, 0);
            gl.glVertex2i(0, 0);
            gl.glTexCoord2f(1, 0);
            gl.glVertex2i(x, 0);
            gl.glTexCoord2f(1, 1);
            gl.glVertex2i(x, y);
            gl.glTexCoord2f(0, 1);
            gl.glVertex2i(0, y);
            gl.glEnd();

            gl.glDisable(GL.GL_BLEND);
            gl.glEnable(GL.GL_DEPTH_TEST);
      }

      /** @see overlay.TextDisplayer#updateText() */
      public void updateText() {
            currentText += completeText.charAt(charLocation++);
            if (charLocation == completeText.length()) {
                  currentText += " \"";
                  finished = true;
            }
      }

      /** Is now active .. ? */
      public boolean isActive() {
            return active;
      }

      /** Set Visibility .. ? */
      public void setActive(boolean b) {
            active = b;
      }

      /** Are we finished displaying text ? */
      public boolean isFinished() {
            return finished;
      }

      /** @see overlay.TextDisplayer#getSize() */
      public Dimension getSize() {
            return dimension;
      }

      /* (non-Javadoc)
       * @see glUtil.Drawable#isDrawable()
       */
      public boolean isDrawable() {
            return true;
      }

      private void buildFont(GL gl) // Build Our Font Display List
      {
            float cx; // Holds Our X Character Coord
            float cy; // Holds Our Y Character Coord

            float characterWidth = 0.0625f;

            base = gl.glGenLists(256); // Creating 256 Display Lists
            gl.glBindTexture(GL.GL_TEXTURE_2D, texturesID[FONT_TEXTURE_ID]);
            // Select Our Font Texture
            for (int loop = 0; loop < 256; loop++) // Loop Through All 256 Lists
                  {
                  cx = (float) (loop % 16) / 16.0f;
                  // X Position Of Current Character
                  cy = (float) (loop / 16) / 16.0f;
                  // Y Position Of Current Character

                  gl.glNewList(base + loop, GL.GL_COMPILE); // Start Building A List
                  gl.glBegin(GL.GL_QUADS); // Use A Quad For Each Character
                  gl.glTexCoord2f(cx, 1 - cy - characterWidth);
                  // Texture Coord (Bottom Left)
                  gl.glVertex2i(0, 0); // Vertex Coord (Bottom Left)
                  gl.glTexCoord2f(cx + characterWidth, 1 - cy - characterWidth);
                  // Texture Coord (Bottom Right)
                  gl.glVertex2i(16, 0); // Vertex Coord (Bottom Right)
                  gl.glTexCoord2f(cx + characterWidth, 1 - cy);
                  // Texture Coord (Top Right)
                  gl.glVertex2i(16, 16); // Vertex Coord (Top Right)
                  gl.glTexCoord2f(cx, 1 - cy); // Texture Coord (Top Left)
                  gl.glVertex2i(0, 16); // Vertex Coord (Top Left)
                  gl.glEnd(); // Done Building Our Quad (Character)
                  gl.glTranslated(12, 0, 0); // Move To The Right Of The Character
                  gl.glEndList(); // Done Building The Display List
            } // Loop Until All 256 Are Built
      }

      private void glPrint(
            GL gl,
            int x,
            int y,
            String string,
            int set,
            float scale) // Where The Printing Happens
      {
            if (set > 1) {
                  set = 1;
            }
            gl.glBindTexture(GL.GL_TEXTURE_2D, texturesID[FONT_TEXTURE_ID]);
            // Select Our Font Texture
            gl.glDisable(GL.GL_DEPTH_TEST); // Disables Depth Testing
            gl.glEnable(GL.GL_BLEND);
            gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);

            gl.glPushMatrix();
            gl.glLoadIdentity();
            gl.glTranslated(x, y, 0);
            gl.glScalef(scale, scale, scale);
            gl.glListBase(base - 32 + (128 * set)); // Choose The Font Set (0 or 1)
            gl.glCallLists(string.length(), GL.GL_BYTE, string.getBytes());
            // Write The Text To The Screen
            gl.glPopMatrix();

            gl.glDisable(GL.GL_BLEND);
            gl.glEnable(GL.GL_DEPTH_TEST); // Enables Depth Testing
      }

      /**
             * @param gl
             * @param i
             * @param string
             */
      private void loadTex(GL gl, int textureID, String textureName)
            throws IOException {

            int[] temp = new int[1]; // create blank 
            gl.glGenTextures(1, temp); // fill with proper gl texture id 
            texturesID[textureID] = temp[0];

            // store gl texture id in correct slot of global array.
            TextureReader.Texture texture = TextureReader.readTexture(textureName);

            //Create Linear Filtered Texture
            gl.glBindTexture(GL.GL_TEXTURE_2D, texturesID[textureID]);
            gl.glTexParameteri(
                  GL.GL_TEXTURE_2D,
                  GL.GL_TEXTURE_MAG_FILTER,
                  GL.GL_LINEAR);
            gl.glTexParameteri(
                  GL.GL_TEXTURE_2D,
                  GL.GL_TEXTURE_MIN_FILTER,
                  GL.GL_LINEAR);

            gl.glTexImage2D(
                  GL.GL_TEXTURE_2D,
                  0,
                  3,
                  texture.getWidth(),
                  texture.getHeight(),
                  0,
                  GL.GL_RGB,
                  GL.GL_UNSIGNED_BYTE,
                  texture.getPixels());

      }

      /**
                   * @param gl
                   * @param i
                   * @param string
                   */
      private void loadRGBATex(GL gl, int textureID, String textureName)
            throws IOException {

            int[] temp = new int[1]; // create blank 
            gl.glGenTextures(1, temp); // fill with proper gl texture id 
            texturesID[textureID] = temp[0];

            // store gl texture id in correct slot of global array.
            TextureReader.Texture texture = TextureReader.readTexture(textureName,true);

            //Create Linear Filtered Texture
            gl.glBindTexture(GL.GL_TEXTURE_2D, texturesID[textureID]);
            gl.glTexParameteri(
                  GL.GL_TEXTURE_2D,
                  GL.GL_TEXTURE_MAG_FILTER,
                  GL.GL_LINEAR);
            gl.glTexParameteri(
                  GL.GL_TEXTURE_2D,
                  GL.GL_TEXTURE_MIN_FILTER,
                  GL.GL_LINEAR);

            gl.glTexImage2D(
                  GL.GL_TEXTURE_2D,
                  0,
                  3,
                  texture.getWidth(),
                  texture.getHeight(),
                  0,
                  GL.GL_RGBA,
                  GL.GL_UNSIGNED_BYTE,
                  texture.getPixels());

      }

      public void init(GLDrawable glDrawable) {
            GL gl = glDrawable.getGL();
            try {
                  loadTex(gl, FONT_TEXTURE_ID, "Data/Fonts/font.png");
                  loadRGBATex(gl, ICON_ID, "Data/Menu/" + name + "Icon.png");
                  loadRGBATex(gl, CONTINUE_TEXT_ID, "Data/Menu/continueIcon.png");
                  loadRGBATex(gl, BACKGROUND_ID, "Data/Menu/textBackground.png");

            } catch (IOException e) {
                  throw new RuntimeException(e);
            }

            buildFont(gl);
      }

}

This is simple class which allows me to show textboxes with text, icon, … if necessary.

once more very sorry, but made another stupid mistake … ! I wrote:


gl.glTexImage2D( 
   GL.GL_TEXTURE_2D, 
   0, 
   3, 
   texture.getWidth(), 
   texture.getHeight(), 
   0, 
   GL.GL_RGBA, 
   GL.GL_UNSIGNED_BYTE, 
   texture.getPixels()); 
 
 } 

while it off coarse has to be:


gl.glTexImage2D( 
   GL.GL_TEXTURE_2D, 
   0, 
   4, 
   texture.getWidth(), 
   texture.getHeight(), 
   0, 
   GL.GL_RGBA, 
   GL.GL_UNSIGNED_BYTE, 
   texture.getPixels()); 
 
 }