I’m doing my on MIPmap generation and I’ve gotten content to display on the screen at lower resolutions it doesn’t appear quite right:
http://captiveimagination.com/download/test_mipmap01.jpg
If I expand the window to be larger so it doesn’t use the mipmapping then I get the correctly displaying image:
http://captiveimagination.com/download/test_mipmap02.jpg
The following is the code I’m using and though I know it’s incredibly inefficient I am simply trying to learn how to generate mipmaps on my own:
package test;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import javax.imageio.ImageIO;
import javax.media.opengl.GL;
import com.sun.opengl.util.BufferUtil;
public class TestMipmapping extends TestBasic {
private int[] vertexes;
private int[] textures;
private int[] textureVbo;
private int programId;
private int vertexShaderId;
private int fragmentShaderId;
private FloatBuffer textureCoordinates;
public void initialize(GL gl) {
super.initialize(gl);
BufferedImage image = null;
try {
image = ImageIO.read(getClass().getClassLoader().getResource("resource/testing.png"));
} catch(Throwable t) {
t.printStackTrace();
}
// Allocate my buffer to hold my two triangles to make up a quad
FloatBuffer buffer = BufferUtil.newFloatBuffer(12); {
buffer.put(0.0f); // Bottom-Left
buffer.put(0.0f);
buffer.put(0.0f);
buffer.put(image.getWidth()); // Bottom-Right
buffer.put(0.0f);
buffer.put(0.0f);
buffer.put(image.getWidth()); // Top-Right
buffer.put(image.getHeight());
buffer.put(0.0f);
buffer.put(0.0f); // Top-Left
buffer.put(image.getHeight());
buffer.put(0.0f);
buffer.rewind();
}
vertexes = new int[1];
gl.glGenBuffersARB(1, vertexes, 0); // Generate a buffer id
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, vertexes[0]); // Bind the buffer
gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB, buffer.capacity() * 4, buffer, GL.GL_STATIC_DRAW_ARB); // Send the vertex buffer data to the video card
textureCoordinates = BufferUtil.newFloatBuffer(8); {
textureCoordinates.put(0.0f); // Top-Left
textureCoordinates.put(1.0f);
textureCoordinates.put(1.0f); // Top-Right
textureCoordinates.put(1.0f);
textureCoordinates.put(1.0f); // Bottom-Right
textureCoordinates.put(0.0f);
textureCoordinates.put(0.0f); // Bottom-Left
textureCoordinates.put(0.0f);
textureCoordinates.rewind();
}
textureVbo = new int[1];
gl.glGenBuffersARB(1, textureVbo, 0);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, textureVbo[0]);
gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB, textureCoordinates.capacity() * 4, textureCoordinates, GL.GL_STATIC_DRAW_ARB);
// Create and bind texture
textures = new int[1];
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
try {
DataBufferByte dbb = (DataBufferByte)image.getRaster().getDataBuffer();
byte[] data = dbb.getData();
ByteBuffer pixels = BufferUtil.newByteBuffer(data.length);
pixels.put(data);
pixels.flip();
int mode = 3; // Modes: 1 = no mipmapping, 2 = auto-mipmapping, 3 = custom mipmapping
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, mode == 1 ? GL.GL_LINEAR : GL.GL_LINEAR_MIPMAP_LINEAR);
if (mode == 2) {
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_GENERATE_MIPMAP, GL.GL_TRUE);
}
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGB, image.getWidth(), image.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, pixels);
if (mode == 3) {
// Generate mipmaps
int w = image.getWidth();
int h = image.getHeight();
int position = 1;
while ((w > 1) || (h > 1)) {
w /= 2;
h /= 2;
if (w == 0) {
w = 1;
} else if (h == 0) {
h = 1;
}
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = bi.createGraphics();
g.drawImage(image, 0, 0, w, h, null);
g.dispose();
DataBufferByte dbb2 = (DataBufferByte)bi.getRaster().getDataBuffer();
byte[] data2 = dbb2.getData();
ByteBuffer pixels2 = BufferUtil.newByteBuffer(data2.length);
pixels2.put(data2);
pixels2.flip();
gl.glTexImage2D(GL.GL_TEXTURE_2D, position, GL.GL_RGB, bi.getWidth(), bi.getHeight(), 0, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, pixels2);
position++;
}
System.out.println("Positions Created: " + position);
}
} catch(Throwable t) {
t.printStackTrace();
}
// Load the GLSL texturing functionality
programId = gl.glCreateProgramObjectARB();
// Vertex Shader
vertexShaderId = gl.glCreateShaderObjectARB(GL.GL_VERTEX_SHADER_ARB);
String source = getShaderSource("texture_coordinates.vert");
gl.glShaderSourceARB(vertexShaderId, 1, new String[] {source}, new int[] {source.length()}, 0);
gl.glCompileShaderARB(vertexShaderId);
int[] result = new int[1];
gl.glGetShaderiv(vertexShaderId, GL.GL_COMPILE_STATUS, result, 0);
if (result[0] != GL.GL_TRUE) {
throw new RuntimeException("Compile of GLSL Shader failed!");
}
gl.glAttachObjectARB(programId, vertexShaderId);
// Fragment Shader
fragmentShaderId = gl.glCreateShaderObjectARB(GL.GL_FRAGMENT_SHADER_ARB);
source = getShaderSource("texture_coordinates.frag");
gl.glShaderSourceARB(fragmentShaderId, 1, new String[] {source}, new int[] {source.length()}, 0);
gl.glCompileShaderARB(fragmentShaderId);
result = new int[1];
gl.glGetShaderiv(fragmentShaderId, GL.GL_COMPILE_STATUS, result, 0);
if (result[0] != GL.GL_TRUE) {
throw new RuntimeException("Compile of GLSL Shader failed!");
}
gl.glAttachObjectARB(programId, fragmentShaderId);
// Link program
gl.glLinkProgramARB(programId);
gl.glGetProgramiv(programId, GL.GL_LINK_STATUS, result, 0);
if (result[0] != GL.GL_TRUE) {
throw new RuntimeException("Linking of GLSL Shader failed!");
}
// Validate log results
gl.glValidateProgramARB(programId);
gl.glGetObjectParameterivARB(programId, GL.GL_OBJECT_INFO_LOG_LENGTH_ARB, result, 0);
int length = result[0];
if (length > 0) {
byte[] log = new byte[length];
gl.glGetInfoLogARB(programId, log.length, new int[length], 0, log, 0);
System.out.println("Log Result: " + new String(log) + " (" + length + ")");
}
gl.glUseProgramObjectARB(programId);
int myTexture = gl.glGetUniformLocationARB(programId, "myTexture");
gl.glUniform1iARB(myTexture, 0);
}
public void draw(GL gl) {
gl.glTranslatef(-400.0f, 0.0f, -800.0f);
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, textureVbo[0]);
gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, 0);
gl.glEnableClientState(GL.GL_VERTEX_ARRAY); {
gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, vertexes[0]);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
gl.glDrawArrays(GL.GL_QUADS, 0, 4);
}
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
}
public static void main(String[] args) throws Exception {
new TestMipmapping();
}
}
Any help is greatly appreciated.