Yes, it’s me again…and yes, it’s the same exact problem I still haven’t been able to solve. I have a concise example showing exactly the problem I’m having and a side-by-side comparison to TextureRenderer that looks exactly as I’d like my texture to appear. I’ve walked through the TextureRenderer, Texture, and TextureData classes line-by-line and still cannot find what it’s doing that makes this massive difference in appearance:
http://captiveimagination.com/download/black_magic.jpg
The first line of text is mine and the second line is TextureRenderer.
Here’s my source code:
package test;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.media.opengl.GL;
import com.sun.opengl.util.j2d.TextureRenderer;
public class TestShape2 extends TestBasic {
private Shape shape1;
private Shape shape2;
private TextureRenderer renderer;
public void initialize(GL gl) {
super.initialize(gl);
try {
shape1 = new Shape(gl); {
BufferedImage image = ImageIO.read(getClass().getClassLoader().getResource("resource/crate.png"));
BufferedImage crate = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB_PRE); {
Graphics2D g = crate.createGraphics();
g.setColor(new Color(1.0f, 0.0f, 0.0f, 1.0f));
g.fillRect(0, 0, 256, 256);
g.drawImage(image, 0, 0, null);
g.dispose();
}
shape1.updateTexture(gl, crate);
}
shape2 = new Shape(gl); {
BufferedImage text = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB_PRE); {
Graphics2D g = text.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Font f = new Font("Arial", Font.BOLD, 24);
g.setFont(f);
g.drawString("Testing", 50.0f, 50.0f);
g.dispose();
}
shape2.updateTexture(gl, text);
}
renderer = new TextureRenderer(256, 256, true, true); {
Graphics2D g = renderer.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Font f = new Font("Arial", Font.BOLD, 24);
g.setFont(f);
g.drawString("Testing", 50.0f, 50.0f);
g.dispose();
renderer.markDirty(0, 0, 256, 256);
}
} catch(Throwable t) {
t.printStackTrace();
}
}
public void draw(GL gl) {
gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
gl.glTranslatef(-50.0f, -50.0f, -500.0f);
shape1.draw(gl, 256.0f, 256.0f);
shape2.draw(gl, 256.0f, 256.0f);
renderer.begin3DRendering(); {
renderer.draw3DRect(0.0f, -50.0f, 0.0f, 0, 0, 256, 256, 1.0f);
renderer.end3DRendering();
}
}
public static void main(String[] args) throws Exception {
new TestShape2();
}
}
package test;
import java.awt.Color;
import java.io.InputStream;
import java.net.URL;
import javax.media.opengl.DebugGL;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCanvas;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;
import com.sun.opengl.util.Animator;
import com.sun.opengl.util.GLUT;
public abstract class TestBasic implements GLEventListener {
protected GLU glu;
protected GLUT glut;
protected GLCanvas canvas;
protected Animator animator;
public TestBasic() {
glu = new GLU();
glut = new GLUT();
JFrame frame = new JFrame(getClass().getSimpleName()); {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setBackground(Color.WHITE);
GLCapabilities caps = new GLCapabilities(); {
}
canvas = new GLCanvas(caps); {
canvas.addGLEventListener(this);
animator = new Animator(canvas);
frame.add(canvas);
}
frame.setVisible(true);
}
animator.start();
}
public void init(GLAutoDrawable drawable) {
GL gl = new DebugGL(drawable.getGL());
gl.setSwapInterval(1); // Vertical sync
gl.glShadeModel(GL.GL_SMOOTH); // Enable smooth shading
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Black background
gl.glClearDepth(1.0f); // Depth buffer setup
gl.glEnable(GL.GL_LINE_SMOOTH);
gl.glEnable(GL.GL_BLEND);
gl.glEnable(GL.GL_POLYGON_SMOOTH);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST); // Really nice perspective calculations
gl.glHint(GL.GL_LINE_SMOOTH_HINT, GL.GL_NICEST);
gl.glHint(GL.GL_POLYGON_SMOOTH_HINT, GL.GL_NICEST);
gl.glEnable(GL.GL_TEXTURE_2D);
initialize(gl);
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
GL gl = drawable.getGL();
if (height <= 0) { // avoid a divide by zero error!
height = 1;
}
float h = (float) width / (float) height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45.0f, h, 1.0, 20000.0);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void display(GLAutoDrawable drawable) {
GL gl = new DebugGL(drawable.getGL());
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); // Clear the screen and depth buffer
gl.glLoadIdentity();
gl.glTranslatef(0.0f, 0.0f, -5.0f);
draw(gl);
}
public void initialize(GL gl) {
}
public abstract void draw(GL gl);
public static final String getShaderSource(String resourceName) {
try {
URL url = TestBasic.class.getClassLoader().getResource("resource/" + resourceName);
InputStream is = url.openStream();
if (is == null) return null;
StringBuffer buffer = new StringBuffer();
int i;
while ((i = is.read()) != -1) {
buffer.append((char)i);
}
return buffer.toString();
} catch(Throwable t) {
throw new RuntimeException(t);
}
}
}
package test;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.SampleModel;
import java.awt.image.SinglePixelPackedSampleModel;
import java.nio.Buffer;
import java.nio.IntBuffer;
import javax.media.opengl.GL;
public class Shape {
private int textureId;
public Shape(GL gl) {
// Generate Texture
int[] tmp = new int[1];
gl.glGenTextures(1, tmp, 0);
textureId = tmp[0];
}
public final void updateTexture(GL gl, BufferedImage image) {
SampleModel sm = image.getRaster().getSampleModel();
int scanlineStride = ((SinglePixelPackedSampleModel)sm).getScanlineStride();
int internalFormat = GL.GL_RGBA;
int pixelFormat = GL.GL_BGRA;
int pixelType = GL.GL_UNSIGNED_INT_8_8_8_8_REV;
int alignment = 1;
DataBuffer data = image.getRaster().getDataBuffer();
Buffer buffer = IntBuffer.wrap(((DataBufferInt)data).getData());
gl.glBindTexture(GL.GL_TEXTURE_2D, textureId);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_GENERATE_MIPMAP, GL.GL_TRUE);
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, internalFormat, image.getWidth(), image.getHeight(), 0, pixelFormat, pixelType, null);
int[] align = new int[1];
int[] rowLength = new int[1];
int[] skipRows = new int[1];
int[] skipPixels = new int[1];
gl.glGetIntegerv(GL.GL_UNPACK_ALIGNMENT, align, 0);
gl.glGetIntegerv(GL.GL_UNPACK_ROW_LENGTH, rowLength, 0);
gl.glGetIntegerv(GL.GL_UNPACK_SKIP_ROWS, skipRows, 0);
gl.glGetIntegerv(GL.GL_UNPACK_SKIP_PIXELS, skipPixels, 0);
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, alignment);
gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, scanlineStride);
gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, 0);
gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, 0);
gl.glTexSubImage2D(GL.GL_TEXTURE_2D, 0, 0, 0, image.getWidth(), image.getHeight(), pixelFormat, pixelType, buffer);
gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, align[0]);
gl.glPixelStorei(GL.GL_UNPACK_ROW_LENGTH, rowLength[0]);
gl.glPixelStorei(GL.GL_UNPACK_SKIP_ROWS, skipRows[0]);
gl.glPixelStorei(GL.GL_UNPACK_SKIP_PIXELS, skipPixels[0]);
}
public final void draw(GL gl, float width, float height) {
gl.glBindTexture(GL.GL_TEXTURE_2D, textureId);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR_MIPMAP_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE);
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
gl.glBegin(GL.GL_QUADS); {
gl.glTexCoord2f(0.0f, 1.0f);
gl.glVertex3f(0.0f, 0.0f, 0.0f);
gl.glTexCoord2f(1.0f, 1.0f);
gl.glVertex3f(width, 0.0f, 0.0f);
gl.glTexCoord2f(1.0f, 0.0f);
gl.glVertex3f(width, height, 0.0f);
gl.glTexCoord2f(0.0f, 0.0f);
gl.glVertex3f(0.0f, height, 0.0f);
gl.glEnd();
}
}
}