Programming > OpenGL
Cannot get compressed texture to work
N-o-N-o:
Greetings,
I've been trying to implement this openGL tutorial with LWJGL
http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/
HoweverI can't seem to obtain anything but a black cube...
Note that I've been trying to get back into java too (which I haven't used since 2011), so the code is probably, uh. Less than optimal.
Here is my code, with long lists of points coordinate, colors, and function removed for clarity. Lemme know if I need to need to add anything.
--- Code: --- private void initOpenGl() {
glfwMakeContextCurrent(window);
// Create OpenGl capabilities
GL.createCapabilities();
// Set the clear color
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
glfwSwapBuffers(window);
}
private synchronized void graphicLoop() {
(...)
try (MemoryStack stack = stackPush()) {
/**** Vertex buffer : our triangle ****/
// Triangle coordinates for a cube
//FloatBuffer triangleBuffer = stack.callocFloat(triangle.length);
FloatBuffer triangleBuffer = stack.callocFloat(cubeTriangles.length);
triangleBuffer.put(cubeTriangles);
triangleBuffer.flip();
/**** Color data ****/
FloatBuffer colorBuffer = stack.callocFloat(colorData.length);
colorBuffer.put(colorData);
colorBuffer.flip();
/**** Buffer objects. One for vertexes, one for colors ****/
int vertexVbo, colorVbo, UV_vbo;
IntBuffer vertexBuffer = stack.callocInt(1);
glGenBuffers(vertexBuffer);
vertexVbo = vertexBuffer.get(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexVbo);
glBufferData(GL_ARRAY_BUFFER, triangleBuffer, GL_STATIC_DRAW);
IntBuffer vertex2Buffer = stack.callocInt(1);
glGenBuffers(vertex2Buffer);
colorVbo = vertex2Buffer.get(0);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
IntBuffer UV_Buffer = stack.callocInt(1);
glGenBuffers(UV_Buffer);
UV_vbo = UV_Buffer.get(0);
glBindBuffer(GL_ARRAY_BUFFER, UV_vbo);
glBufferData(GL_ARRAY_BUFFER, colorBuffer, GL_STATIC_DRAW);
int vbaName;
IntBuffer vbaBuffer = stack.callocInt(1);
vbaBuffer.put(glGenVertexArrays());
vbaName = vbaBuffer.get(0);
glBindVertexArray(vbaName);
/**** Program ****/
IntBuffer shaderBuffer = stack.callocInt(4);
/*int vertexShader;
shaderBuffer.put(0, glCreateShader(GL_VERTEX_SHADER));
vertexShader = shaderBuffer.get(0);
glShaderSource(vertexShader,readGLSLfile("vertex.glsl"));
glCompileShader(vertexShader);*/
int viewShader;
shaderBuffer.put(2, glCreateShader(GL_VERTEX_SHADER));
viewShader = shaderBuffer.get(2);
glShaderSource(viewShader, readGLSLfile("mvpVertex.glsl"));
int colorShader;
shaderBuffer.put(1,glCreateShader(GL_FRAGMENT_SHADER));
colorShader = shaderBuffer.get(1);
glShaderSource(colorShader, readGLSLfile("color.glsl"));
//Build glsl program
int pID;
shaderBuffer.put(3, glCreateProgram());
pID = shaderBuffer.get(3);
//glAttachShader(pID, vertexShader);
glAttachShader(pID, viewShader);
glAttachShader(pID, colorShader);
glLinkProgram(pID);
// Check for errors
int status = glGetProgrami(pID, GL_LINK_STATUS);
if (status == 0) {
int infoLogLength = glGetProgrami(pID, GL_INFO_LOG_LENGTH);
String strInfoLog = null;
strInfoLog = glGetProgramInfoLog(pID, infoLogLength);
System.err.printf("Linker failure: %s\n", strInfoLog);
}
Matrix4f mvp = new Matrix4f()
.perspective((float) Math.toRadians(90.0), 1.0f, 0.1f, 100.0f)
.lookAt(4.0f, 3.0f, 3.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f);
FloatBuffer mvp_buffer = stack.callocFloat(16);
mvp.get(mvp_buffer);
IntBuffer intBuffer = stack.callocInt(1);
intBuffer.put(glGetUniformLocation(pID, "MVP"));
int mvpLocation = intBuffer.get(0);
/**** Compressed texture ****/
CompressedTexture texture = new CompressedTexture("uvtemplate.DDS");
int textureGLSL_ID = glGetUniformLocation(pID, "myTextureSampler");
while (!myControlHandler.getWindowShouldClose()) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pID);
glUniformMatrix4fv(mvpLocation, false, mvp_buffer);
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.getTextureID());
// Set our "myTextureSampler" sampler to use Texture Unit 0
glUniform1i(textureGLSL_ID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexVbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, colorVbo);
glVertexAttribPointer(1, 3, GL_FLOAT, false, 0, 0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, UV_vbo);
glVertexAttribPointer(2, 2, GL_FLOAT, false, 0, 0);
glDrawArrays(GL_TRIANGLES, 0, 3*12);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glfwSwapBuffers(window);
}
}
}
--- End code ---
--- Code: ---public class CompressedTexture {
private int textureID;
private int height;
private int width;
private int linearSize;
private int mipMapCount;
private int fourCC;
private int components;
private int format;
private int dataLength;
private ByteBuffer textureData;
public CompressedTexture(String fileName) {
parseFile(fileName);
textureID = glGenTextures();
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
loadMipmaps();
}
public void parseFile(String fileName) {
fileName = "res/" + fileName;
try (FileInputStream reader = new FileInputStream (fileName)) {
byte[] header = new byte[4];
reader.read(header);
if (new String (header).compareTo(new String("DDS ")) != 0)
throw new IOException("Not a DDS file");
readHeader(reader);
readData(reader);
} catch (IOException x) {
System.err.println(x);
}
components = (fourCC == 0x31545844) ? 3 : 4;
switch (fourCC) {
case 0x30315844://DX10
format = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
break;
case 0x31545844://DXT1
format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
break;
case 0x33545844://DXT3
format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
break;
case 0x35545844://DXT5
format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
break;
default:
format = -1;
try {
throw new Exception("Unknown compressed texture type\n ");
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
private void readHeader(FileInputStream reader) throws IOException {
/******* Reading header *******/
byte[] header = new byte[4];
reader.skip(8);
reader.read(header);
height = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN).getInt();
reader.read(header);
width = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN).getInt();
reader.read(header);
linearSize = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN).getInt();
reader.skip(4);
reader.read(header);
mipMapCount = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN).getInt();
reader.skip(52);
reader.read(header);
fourCC = ByteBuffer.wrap(header).order(ByteOrder.LITTLE_ENDIAN).getInt();
System.out.println("Height : " + height);
System.out.println("width : " + width);
System.out.println("linearSize : " + linearSize);
System.out.println("mipMapCount : " + mipMapCount);
System.out.printf("fourCC : %x\n", fourCC);
}
private void readData(FileInputStream reader) throws IOException {
/******* Reading data *******/
int buffSize = mipMapCount > 1 ? linearSize * 2 : linearSize;
//MemoryUtil.MemoryAllocator memAlloc = MemoryUtil.getAllocator();
//this.textureData = MemoryUtil.memCalloc(buffSize);
this.textureData = ByteBuffer.allocate(buffSize);
this.dataLength = reader.read(textureData.array(), 0, buffSize);
textureData.flip();
}
private void loadMipmaps() {
int blockSize = (format==GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
int loopWidth = this.width;
int loopHeight = this.height;
ByteBuffer data = BufferUtils.createByteBuffer(dataLength);
data.put(textureData);
data.rewind();
for(int level = 0; level < mipMapCount; ++level) {
int size = ((loopWidth+3)/4)*((loopHeight+3)/4)*blockSize;
ByteBuffer mipMapData = BufferUtils.createByteBuffer(size);
byte[] mipMapByte = new byte[size];
data.get(mipMapByte);
mipMapData.put(mipMapByte);
mipMapData.rewind();
glCompressedTexImage2D(GL_TEXTURE_2D,
level,
format,
loopWidth,
loopHeight,
0,
mipMapData);
loopWidth /= 2;
loopHeight /= 2;
}
}
--- End code ---
I hope I'm not breaking any rules with first post.
Any help would be greatly appreciated.
EDIT :
Ah. I suppose I should add GLSL files !
--- Code: ---#version 330 core
// Interpolated values from the vertex shaders
in vec3 fragmentColor;
// Interpolated values from the vertex shaders
in vec2 UV;
// Ouput data
out vec3 color;
// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;
void main(){
// Output color = color specified in the vertex shader,
// interpolated between all 3 surrounding vertices
// color = fragmentColor;
color = texture( myTextureSampler, UV ).rgb;
// color = vec3(1, UV );//colors the cube : UV values are set
}
--- End code ---
--- Code: ---#version 330 core
//in vec3 vertexPosition_modelspace;
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexColor;
layout(location = 2) in vec2 vertexUV;
// Output data ; will be interpolated for each fragment.
out vec2 UV;
out vec3 fragmentColor;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
// Color / UV
fragmentColor = vertexColor;
UV = vertexUV;
}
--- End code ---
I've been editing the code for some time now, and i'm honestly at a loss...
spasi:
Try calling GLUtil.setupDebugMessageCallback(); after GL.createCapabilities(); to make sure the code isn't raising any OpenGL errors.
I would also try a simpler texture (uncompressed, no mipmaps) to make sure the shader doesn't have any issues.
N-o-N-o:
Thanks for your answer. I've made a new Bitmap texture class, and added the debug callback as you advised.
Here are the callback messages :
--- Quote ---[LWJGL] OpenGL debug message
ID: 0x20071
Source: API
Type: OTHER
Severity: NOTIFICATION
Message: Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
[LWJGL] OpenGL debug message
ID: 0x20071
Source: API
Type: OTHER
Severity: NOTIFICATION
Message: Buffer detailed info: Buffer object 2 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
[LWJGL] OpenGL debug message
ID: 0x20071
Source: API
Type: OTHER
Severity: NOTIFICATION
Message: Buffer detailed info: Buffer object 3 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_STATIC_DRAW) will use VIDEO memory as the source for buffer object operations.
--- End quote ---
Weird thing is, the program doesn't close on clicking the close button (crashes instead). This behaviour stop if I remove the display loop.
Here's the new BitmapTexture class :
--- Code: ---public class BitmapTexture {
private int textureID;
private int dataPos;
private int imageSize;
private int height;
private int width;
private int dataLength;
private ByteBuffer textureData;
public BitmapTexture(String fileName) {
parseFile(fileName);
textureID = glGenTextures();
// "Bind" the newly created texture : all future texture functions will modify this texture
glBindTexture(GL_TEXTURE_2D, textureID);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
width,
height,
0,
GL_BGR,
GL_UNSIGNED_BYTE,
textureData);
}
public void parseFile(String fileName) {
fileName = "res/" + fileName;
try (FileInputStream reader = new FileInputStream (fileName)) {
readHeader(reader);
readData(reader);
} catch (IOException x) {
System.err.println(x);
}
}
private void readHeader(FileInputStream reader) throws IOException {
/******* Reading header *******/
byte[] header = new byte[54];
reader.read(header);
if (header[0] !='B' || header[1] != 'M')
throw new IOException("Not a BMP file");
/****** reading into a ByteBuffer ******/
ByteBuffer intBuffer = ByteBuffer.allocate(24);
intBuffer.put(header, 0x1E, 4);
intBuffer.put(header, 0x1C, 4);
intBuffer.put(header, 0x0A, 4);
intBuffer.put(header, 0x12, 4);
intBuffer.put(header, 0x16, 4);
intBuffer.put(header, 0x22, 4);
intBuffer.flip();
if (intBuffer.order(ByteOrder.LITTLE_ENDIAN).getInt() != 0 ||
intBuffer.order(ByteOrder.LITTLE_ENDIAN).getInt() != 24)
throw new IOException("Not a valid BMP file");
dataPos = intBuffer.order(ByteOrder.LITTLE_ENDIAN).getInt();
height = intBuffer.order(ByteOrder.LITTLE_ENDIAN).getInt();
width = intBuffer.order(ByteOrder.LITTLE_ENDIAN).getInt();
imageSize = intBuffer.order(ByteOrder.LITTLE_ENDIAN).getInt();
System.out.println("dataPos : " + dataPos);
System.out.println("Height : " + height);
System.out.println("width : " + width);
System.out.println("imageSize : " + imageSize);
}
private void readData(FileInputStream reader) throws IOException {
/******* Reading data *******/
textureData = ByteBuffer.allocate(imageSize);
dataLength = reader.read(textureData.array(), 0, imageSize);
textureData.flip();
}
public int getTextureID() {
return textureID;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public ByteBuffer getTextureData() {
return textureData;
}
public void flipTextureData() {
textureData.flip();
}
}
--- End code ---
spasi:
Hard to be helpful without seeing more of the code. Could you please prepare an MVCE?
Btw, why not use stb_image instead of parsing the .bmp manually?
N-o-N-o:
I'll try to use stb_image to see if it fixes things first. I'll keep you updated with a workable exemple after that.
Navigation
[0] Message Index
[#] Next page
Go to full version