LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Cornix on February 20, 2013, 22:28:39

Title: Create a 2D Texture pixel data
Post by: Cornix on February 20, 2013, 22:28:39
Hi, i am trying to create a 2D texture from a 3-dimensional byte array.

Right now my code looks somewhat like this:

ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.nativeOrder());
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
buf.put(pixel_data[x][y][0]);
buf.put(pixel_data[x][y][1]);
buf.put(pixel_data[x][y][2]);
buf.put(pixel_data[x][y][3]);
}
}
buf.flip();
texture_id = GL11.glGenTextures();
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);


But when i try to draw something with this texture the result is always pure white.
What am I doing wrong?


Edit:
I know that the drawing works, i manage to load textures via the slick-util texture loader and draw them perfectly.
Title: Re: Create a 2D Texture pixel data
Post by: Elviz on February 21, 2013, 00:54:08
Add the following after the call to glGenTextures:

GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture_id);

Also, make sure to move the y loop before the x loop:

for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {


This assumes that the source image is already in bottom-up format. If not, simply reverse the line order:

for (int y = height - 1; y >= 0; y--) {
for (int x = 0; x < width; x++) {
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 21, 2013, 10:16:09
Thanks for the answer but that doesnt do anything. The picture is still pure white across the board.
Title: Re: Create a 2D Texture pixel data
Post by: abcdef on February 21, 2013, 10:46:31
You haven't posted your rendering code but have you enabled GL_TEXTURE_2D?
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 21, 2013, 11:16:09
I have updated my first post to hopefully clarify.

The drawing works, i am able to draw textures which i have loaded via the slick-util texture loader.
My rendering code looks like this:

GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture_id);
GL11.glMatrixMode(GL11.GL_TEXTURE);
GL11.glLoadIdentity();
GL11.glScalef(1f / width, 1f / height, 1);

GL11.glBegin(GL11.GL_QUADS);

GL11.glColor4f(1f, 1f, 1f, 1f);
GL14.glSecondaryColor3f(0f, 0f, 0f);
GL11.glTexCoord2f( 0,  0); GL11.glVertex3f(256, 256, 1);
GL11.glTexCoord2f(32,  0); GL11.glVertex3f(320, 256, 1);
GL11.glTexCoord2f(32, 32); GL11.glVertex3f(320, 320, 1);
GL11.glTexCoord2f( 0, 32); GL11.glVertex3f(256, 320, 1);

GL11.glEnd();

(I use front-face culling, dont worry about the order of vertices)
Title: Re: Create a 2D Texture pixel data
Post by: quew8 on February 21, 2013, 15:40:22
Maybe a stupid answer, but have you actually checked the content of your buffer before loading into opengl?
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 21, 2013, 15:47:37
Quote from: quew8 on February 21, 2013, 15:40:22
Maybe a stupid answer, but have you actually checked the content of your buffer before loading into opengl?

I did.
It seems to be correct.

Also tested the texture id, its a positive number.
Title: Re: Create a 2D Texture pixel data
Post by: abcdef on February 22, 2013, 10:47:07
Aren't texture coordinates meant to be in the range 0-1? You have 0-32 (never drawn thigns in TEXTURE mode though, so this might be normal)

I still don't see you enabling GL_TEXTURE_2D (might be else where though)

Lastly what type of image format are you trying to load? Its hard to tell. You use types GL11.GL_UNSIGNED_BYTE, does your pixel_data contain byte values. They might be signed (so you might need to do a &FF to convert to unsigned byte
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 22, 2013, 11:50:36
Quote from: abcdef on February 22, 2013, 10:47:07
Aren't texture coordinates meant to be in the range 0-1? You have 0-32 (never drawn thigns in TEXTURE mode though, so this might be normal)
Normally they are in the range of 0-1 but after this line of code:
GL11.glScalef(1f / width, 1f / height, 1);
I can use the exact pixel coordinates.
Although even without the line, since i set the wrap mode to be "Repeat" it would still work.

Quote from: abcdef on February 22, 2013, 10:47:07
I still don't see you enabling GL_TEXTURE_2D (might be else where though)
I do it at another point in the program. As i said, i can draw textures loaded via the slick-util.

Quote from: abcdef on February 22, 2013, 10:47:07Lastly what type of image format are you trying to load? Its hard to tell. You use types GL11.GL_UNSIGNED_BYTE, does your pixel_data contain byte values. They might be signed (so you might need to do a &FF to convert to unsigned byte
I try to use a 3 dimensional byte table to define the picture myself. No format used at all. Just raw byte data.
Title: Re: Create a 2D Texture pixel data
Post by: Fool Running on February 22, 2013, 13:37:17
Try using RGBA instead of RGBA8 (it's what I've used in my code and it works fine for me :P):
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 22, 2013, 14:33:23
Quote from: Fool Running on February 22, 2013, 13:37:17
Try using RGBA instead of RGBA8 (it's what I've used in my code and it works fine for me :P):
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
Thank you for the reply, but unfortunately it didnt work.
What exactly is the difference between RGBA and RGBA8?

On a sidenote: Doing "& 0xFF" did not work either.


Here is the entire code for that class:
package graphics2D;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
import java.util.Arrays;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL14;

public class Tex2D {

private final float scale_width;
private final float scale_height;
private final int width;
private final int height;
private final int texture_id;

public Tex2D(final byte[][][] pixel_data, final Filter_Mode min_filter, final Filter_Mode mag_filter, final Wrap_Mode vertical_wrap, final Wrap_Mode horizontal_wrap){
int w;
int h;
w = pixel_data.length;
if (w == 0){
throw new TextureSizeException("Can not create texture with width of 0");
}else{
h = pixel_data[0].length;
if (h == 0){
throw new TextureSizeException("Can not create texture with height of 0");
}
}
if (!is_power_of_two(w)){
w = next_power_of_two(w);
}
if (!is_power_of_two(h)){
h = next_power_of_two(h);
}
this.width = w;
this.height = h;
this.scale_width = 1f / this.width;
this.scale_height = 1f / this.height;

final ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.nativeOrder());
for (int y = 0; y < this.height; y++){
for (int x = 0; x < this.width; x++){
buf.put((byte) (pixel_data[x][y][0] & 0xFF));
buf.put((byte) (pixel_data[x][y][1] & 0xFF));
buf.put((byte) (pixel_data[x][y][2] & 0xFF));
buf.put((byte) (pixel_data[x][y][3] & 0xFF));
}
}
buf.flip();

this.texture_id = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
set_filter(true, min_filter);
set_filter(false, mag_filter);
set_wrap(true, horizontal_wrap);
set_wrap(false, vertical_wrap);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, this.width, this.height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
}

public void print_buffer(){
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.nativeOrder());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
byte[] data = new byte[buf.limit()];
buf.get(data);
buf.clear();
System.out.println(Arrays.toString(data));
}

public void bind(){
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
GL11.glMatrixMode(GL11.GL_TEXTURE);
GL11.glLoadIdentity();
GL11.glScalef(this.scale_width, this.scale_height, 1);
}

public void remove(){
IntBuffer texBuf = ByteBuffer.allocateDirect(4).asIntBuffer();
texBuf.put(this.texture_id);
texBuf.flip();
GL11.glDeleteTextures(texBuf);
}

private static final int next_power_of_two(int value){
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value++;
return value;
}

private static final boolean is_power_of_two(final int value){
return (value & (~value + 1)) == value;
}

private static final void set_wrap(final boolean horizontal, final Wrap_Mode wrap){
final int type = horizontal ? GL11.GL_TEXTURE_WRAP_S : GL11.GL_TEXTURE_WRAP_T;
switch (wrap){
case REPEAT :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_REPEAT);
break;
case MIRRORED_REPEAT :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL14.GL_MIRRORED_REPEAT);
break;
case CLAMP :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_CLAMP);
break;
case CLAMP_TO_BORDER :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL13.GL_CLAMP_TO_BORDER);
break;
case CLAMP_TO_EDGE :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL12.GL_CLAMP_TO_EDGE);
break;
}
}

private static final void set_filter(final boolean min, final Filter_Mode filter){
final int type = min ? GL11.GL_TEXTURE_MIN_FILTER : GL11.GL_TEXTURE_MAG_FILTER;
switch (filter){
case LINEAR :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_LINEAR);
break;
case NEAREST :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_NEAREST);
break;
}
}

public static enum Filter_Mode {
LINEAR, NEAREST;
}

public static enum Wrap_Mode {
REPEAT, MIRRORED_REPEAT, CLAMP, CLAMP_TO_BORDER, CLAMP_TO_EDGE;
}

private static final class TextureSizeException extends RuntimeException{
private static final long serialVersionUID = -8911712330468875206L;
public TextureSizeException(String string) {
super(string);
}
}

}



And this is how i use it:

private Tex2D tex;

public void initialize() {
byte[][][] pixel_data = new byte[6][6][4];
byte i = 0;
for (int x = 0; x < pixel_data.length; x++){
for (int y = 0; y < pixel_data[0].length; y++){
pixel_data[x][y][0] = i;
pixel_data[x][y][1] = i;
pixel_data[x][y][2] = i;
pixel_data[x][y][3] = i;
i++;
}
}
tex = new Tex2D(pixel_data, Tex2D.Filter_Mode.NEAREST, Tex2D.Filter_Mode.NEAREST, Tex2D.Wrap_Mode.REPEAT, Tex2D.Wrap_Mode.REPEAT);
}

public void update() {
tex.bind();
GL11.glBegin(GL11.GL_QUADS);

GL11.glColor4f(1f, 1f, 1f, 1f);
GL14.glSecondaryColor3f(0f, 0f, 0f);
GL11.glTexCoord2f( 0,  0); GL11.glVertex3f(256, 256, 1);
GL11.glTexCoord2f(32,  0); GL11.glVertex3f(320, 256, 1);
GL11.glTexCoord2f(32, 32); GL11.glVertex3f(320, 320, 1);
GL11.glTexCoord2f( 0, 32); GL11.glVertex3f(256, 320, 1);

GL11.glEnd();
}
Title: Re: Create a 2D Texture pixel data
Post by: quew8 on February 24, 2013, 11:52:31
RGBA8 uses 8 bits per component. RGBA uses a default size dependent on hardware and implementation.
Something just occurred to me. There is a glGetTexture function you could use to ensure the data openGL has is the data you're giving it.
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 24, 2013, 14:23:30
Quote from: quew8 on February 24, 2013, 11:52:31
RGBA8 uses 8 bits per component. RGBA uses a default size dependent on hardware and implementation.
Something just occurred to me. There is a glGetTexture function you could use to ensure the data openGL has is the data you're giving it.

Thank you for the information.
I was using:
public String test(){
ByteBuffer buf = ByteBuffer.allocateDirect(4);
buf.order(ByteOrder.nativeOrder());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture_id);
    GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE,
       buf);
    byte[] data = new byte[buf.limit()];
    buf.get(data);
    buf.clear();
   
    return Arrays.toString(data);
}

To test the pixel data and the results i got with this function were identical to the input i made.

Now, this piece of code is not very long, would it be possible if somebody could maybe try to implement a data structure like mine and see if he/she could get it done?
I would really appreciate any further help.
Title: Re: Create a 2D Texture pixel data
Post by: quew8 on February 25, 2013, 19:48:31
So this has been bugging me and I decided to write my own implementation that just loads a single colour for simplicity:

public static int createColourTexture(Colour c, int width, int height) {
        int id = createTextureID();
        GL11.glBindTexture(GL11.GL_TEXTURE_2D, id);
       
        int texWidth = get2Fold(width);
        int texHeight = get2Fold(height);
       
        float[] fdata = new float[texWidth * texHeight * 4];
        for(int h = 0, pos = 0; h < texHeight; h++) {
            for(int w = 0; w < texWidth; w++, pos++) {
                fdata[pos++] = c.getRed();
                fdata[pos++] = c.getGreen();
                fdata[pos++] = c.getBlue();
                fdata[pos] = c.getAlpha();
            }
        }
        FloatBuffer fb = BufferUtils.createFloatBuffer(fdata);

        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
       
        GL11.glTexImage2D(
                GL11.GL_TEXTURE_2D,
                0,
                GL11.GL_RGBA,
                texWidth,
                texHeight,
                0,
                GL11.GL_RGBA,
                GL11.GL_FLOAT,
                fb
                );
       
        GLException.checkGLError();
        table.put(ref, id);
        return id;
    }

Using floats, this worked like a charm. I could not however get a byte or int version to work in the slightest (although they always appeared black for me rather than white so probably we're having different problems). Maybe you could try a float based version (as a test)
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 26, 2013, 12:04:58
Thank you for the reply.
But it doesnt seem to work for me.

First of all, as it seems i am using an old version of lwjgl since there is neither a function to create a FloatBuffer from a float array nor can i resolve the type GLException in my build.

But even if i try to use a float buffer instead of a byte-buffer it is still just a pure white square.
Title: Re: Create a 2D Texture pixel data
Post by: quew8 on February 26, 2013, 18:46:55
Really sorry, GLException is one of my own classes and the float buffer from array is a utility method of mine. I should have remembered to remove these. Sorry again.
You also have to change the type argument in glTexImage2D from GL_UNSIGNED_BYTE to GL_FLOAT
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 26, 2013, 19:13:52
This was the code i used:
final ByteBuffer byteBuf = ByteBuffer.allocateDirect(width * height * 16);
byteBuf.order(ByteOrder.nativeOrder());
final FloatBuffer floatBuf = byteBuf.asFloatBuffer();
for (int y = 0; y < this.height; y++){
for (int x = 0; x < this.width; x++){
floatBuf.put(pixel_data[x][y][0]);
floatBuf.put(pixel_data[x][y][1]);
floatBuf.put(pixel_data[x][y][2]);
floatBuf.put(pixel_data[x][y][3]);
}
}
floatBuf.flip();
// FloatBuffer fb = BufferUtils.createFloatBuffer(width * height * 4);
// for (int y = 0; y < this.height; y++){
// for (int x = 0; x < this.width; x++){
// fb.put(pixel_data[x][y][0]);
// fb.put(pixel_data[x][y][1]);
// fb.put(pixel_data[x][y][2]);
// fb.put(pixel_data[x][y][3]);
// }
// }
// fb.flip();

this.texture_id = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
set_filter(true, min_filter);
set_filter(false, mag_filter);
set_wrap(true, horizontal_wrap);
set_wrap(false, vertical_wrap);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, this.width, this.height, 0, GL11.GL_RGBA, GL11.GL_FLOAT, floatBuf);

The commented part uses the bufferUtils from lwjgl, it also does not work.
I just cant get any other color but pure white, no matter what i input.

Could maybe somebody try this exact code of mine on his/her machine? Although i highly doubt it it might be hardware related.
Title: Re: Create a 2D Texture pixel data
Post by: abcdef on February 27, 2013, 09:54:18
Can you post some values of you texture data? I can't help but think this is the problem
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 27, 2013, 13:09:58
Quote from: abcdef on February 27, 2013, 09:54:18
Can you post some values of you texture data? I can't help but think this is the problem

Here is what i did:
byte[][][] pixel_data = new byte[2][2][4];
byte i = 0;
for (int x = 0; x < pixel_data.length; x++){
for (int y = 0; y < pixel_data[0].length; y++){
pixel_data[x][y][0] = i;
pixel_data[x][y][1] = i;
pixel_data[x][y][2] = i;
pixel_data[x][y][3] = i;
i++;
}
}
tex = new CsTexture2D(pixel_data, CsTexture2D.Filter_Mode.NEAREST, CsTexture2D.Filter_Mode.NEAREST, CsTexture2D.Wrap_Mode.REPEAT, CsTexture2D.Wrap_Mode.REPEAT);
System.out.println(tex.toString());


with

public String test(){
ByteBuffer buffer = BufferUtils.createByteBuffer(4 * width * height);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buffer);
byte[] data = new byte[buffer.limit()];
buffer.get(data);
buffer.clear();
return Arrays.toString(data);
}


And the output is:
Quote[0, 0, 0, 0, 2, 2, 2, 2, 1, 1, 1, 1, 3, 3, 3, 3]

But the texture looks all pure white.
Title: Re: Create a 2D Texture pixel data
Post by: abcdef on February 27, 2013, 13:36:44
Your alpha number (RGBA...(A part))  has values 0,1,2,3.

Because you are doing GL_UNSIGNED_BYTE you are effectively treating the values like integers. Of course opengl clamps the values to [0,1] but you are passing integers so opengl takes the integer range [0,255] and normalised it to [0,1]

You alpha values therefore map to 0,0.004,0.008,0.012 (basically all close to 0), this means you are almost transparent

Secondly your colors map to  (0,0,0),(0.004,0.004,0.004),...etc. These are so close to all being black. If you want to make it all red then you need to use (255,0,0,1)
Title: Re: Create a 2D Texture pixel data
Post by: Fool Running on February 27, 2013, 14:16:50
Try adding the following to your initialization code:
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

I think there is some bad texture blending going on.

EDIT: Also, if you are still doing the following:
GL11.glMatrixMode(GL11.GL_TEXTURE);
GL11.glLoadIdentity();
GL11.glScalef(this.scale_width, this.scale_height, 1);

The GL_TEXTURE should be GL_TEXTURE_MATRIX and you probably should switch back to the GL_MODELVIEW_MATRIX when you are done with your texture scaling.
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on February 27, 2013, 15:24:59
Thank you both for the replies!

Quote from: abcdef on February 27, 2013, 13:36:44
Your alpha number (RGBA...(A part))  has values 0,1,2,3.

Because you are doing GL_UNSIGNED_BYTE you are effectively treating the values like integers. Of course opengl clamps the values to [0,1] but you are passing integers so opengl takes the integer range [0,255] and normalised it to [0,1]

You alpha values therefore map to 0,0.004,0.008,0.012 (basically all close to 0), this means you are almost transparent

Secondly your colors map to  (0,0,0),(0.004,0.004,0.004),...etc. These are so close to all being black. If you want to make it all red then you need to use (255,0,0,1)
I know the colors in that example were a bad choice, but believe me, i have tested this with many, many different variations and all kinds of input. It has always been the same white square, with no value has there been any change.

Quote from: Fool Running on February 27, 2013, 14:16:50EDIT: Also, if you are still doing the following:
GL11.glMatrixMode(GL11.GL_TEXTURE);
GL11.glLoadIdentity();
GL11.glScalef(this.scale_width, this.scale_height, 1);

The GL_TEXTURE should be GL_TEXTURE_MATRIX and you probably should switch back to the GL_MODELVIEW_MATRIX when you are done with your texture scaling.
Could you elaborate a little bit more on this? I have been using "GL11.glMatrixMode(GL11.GL_TEXTURE);" for quite some time now and never had any trouble with it. What exactly would be different using "GL11.glMatrixMode(GL11.GL_TEXTURE_MATRIX );"? I am eager to learn more about it.
Also, for what purpose do i need to switch back to the modelview-matrix? I havent done it ever before, it would be nice to know before the next problem emerges.


Quote from: Fool Running on February 27, 2013, 14:16:50
Try adding the following to your initialization code:
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

I think there is some bad texture blending going on.
I did that, and now finally something changed!
At first i saw nothing, the screen was complete black and nothing was drawn at all.
But then i started to draw a pure white square first and then my own texture and now i can see a grey square instead of a white one.

So i played around a little bit with the blend-functions and i set it to "GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);" and now i can actually change the color of the square. Before it was only grey, always, no matter what i used as input.
But of course, i can not keep using "GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ZERO);", so, if any of you knows a reason why this is happening i would be happy to hear about it.
Title: Re: Create a 2D Texture pixel data
Post by: Fool Running on February 28, 2013, 13:41:16
Quote from: Cornix on February 27, 2013, 15:24:59
Quote from: Fool Running on February 27, 2013, 14:16:50EDIT: Also, if you are still doing the following:
GL11.glMatrixMode(GL11.GL_TEXTURE);
GL11.glLoadIdentity();
GL11.glScalef(this.scale_width, this.scale_height, 1);

The GL_TEXTURE should be GL_TEXTURE_MATRIX and you probably should switch back to the GL_MODELVIEW_MATRIX when you are done with your texture scaling.
Could you elaborate a little bit more on this? I have been using "GL11.glMatrixMode(GL11.GL_TEXTURE);" for quite some time now and never had any trouble with it. What exactly would be different using "GL11.glMatrixMode(GL11.GL_TEXTURE_MATRIX );"? I am eager to learn more about it.
Also, for what purpose do i need to switch back to the modelview-matrix? I havent done it ever before, it would be nice to know before the next problem emerges.
Sorry, I confused myself. :-\ GL_TEXTURE is correct. GL_TEXTURE_MATRIX is for retrieving the current texture matrix. Also, I meant you should switch back to GL11.glMatrixMode(GL_MODELVIEW) and not GL_MODELVIEW_MATRIX (also used for retrieving the current matrix). If you don't switch back to the GL_MODELVIEW matrix, then any other changes you do to the matrix (glTranslate(), glRotate(), etc.) will change the texture matrix instead of the modelview matrix. You aren't doing anything like that, yet, but you probably will eventually.

I tried to get your code working. Without the texture scaling code, it works fine for me:
EDIT: Got it to work with the scaling:
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;


public class TestIt
{
Tex2D tex;
int width, height;

public static void main(String[] args) {
TestIt game = new TestIt();
game.init();
game.loop();
}

private void loop() {
while(!Display.isCloseRequested())
{
//DRAW
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glLoadIdentity();

tex.bind();
GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
GL11.glBegin(GL11.GL_QUADS);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2f((width - 150)/2, 10f);
GL11.glTexCoord2f(10.0f, 0.0f);
GL11.glVertex2f((width + 150)/2, 10f);
GL11.glTexCoord2f(10.0f, 10.0f);
GL11.glVertex2f((width + 150)/2, 150 + 10);
GL11.glTexCoord2f(0.0f, 10.0f);
GL11.glVertex2f((width - 150)/2, 150 + 10);
GL11.glEnd();

Display.update();
Display.sync(60);
}
Display.destroy();
}

private void init() {
//Display
try {
Display.setTitle("Initialising...");
Display.setFullscreen(false);
Display.create();

GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();

width = Display.getDisplayMode().getWidth();
height = Display.getDisplayMode().getHeight();
GL11.glOrtho(0, width, height, 0, -1, 1);

GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();

GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

byte[][][] pixel_data = new byte[16][16][4];
int i = 0;
for (int x = 0; x < pixel_data.length; x++){
for (int y = 0; y < pixel_data[0].length; y++){
pixel_data[x][y][0] = (byte)(Math.random() * 255);
pixel_data[x][y][1] = (byte)(Math.random() * 255);
pixel_data[x][y][2] = (byte)(Math.random() * 255);
pixel_data[x][y][3] = (byte)(i % 0xFF);
i++;
}
}
tex = new Tex2D(pixel_data, Tex2D.Filter_Mode.NEAREST,
Tex2D.Filter_Mode.NEAREST, Tex2D.Wrap_Mode.REPEAT,
Tex2D.Wrap_Mode.REPEAT);

} catch(LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
}

}

and
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Arrays;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL14;
import org.lwjgl.util.Color;


public class Tex2D
{
private final float scale_width;
private final float scale_height;
private final int width;
private final int height;
private final int texture_id;

public Tex2D(final byte[][][] pixel_data, final Filter_Mode min_filter,
final Filter_Mode mag_filter, final Wrap_Mode vertical_wrap,
final Wrap_Mode horizontal_wrap){
int w;
int h;
w = pixel_data.length;
if (w == 0){
throw new TextureSizeException("Can not create texture with width of 0");
}else{
h = pixel_data[0].length;
if (h == 0){
throw new TextureSizeException("Can not create texture with height of 0");
}
}
if (!is_power_of_two(w)){
w = next_power_of_two(w);
}
if (!is_power_of_two(h)){
h = next_power_of_two(h);
}
this.width = w;
this.height = h;
this.scale_width = 1f / this.width;
this.scale_height = 1f / this.height;

final ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder());
for (int y = 0; y < this.height; y++){
for (int x = 0; x < this.width; x++){
buf.put(pixel_data[x][y][0]);
buf.put(pixel_data[x][y][1]);
buf.put(pixel_data[x][y][2]);
buf.put(pixel_data[x][y][3]);
}
}
buf.flip();

this.texture_id = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
set_filter(true, min_filter);
set_filter(false, mag_filter);
set_wrap(true, horizontal_wrap);
set_wrap(false, vertical_wrap);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, this.width, this.height,
0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
}

public void print_buffer(){
ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
buf.order(ByteOrder.nativeOrder());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
GL11.glGetTexImage(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, buf);
byte[] data = new byte[buf.limit()];
buf.get(data);
buf.clear();
System.out.println(Arrays.toString(data));
}

public void bind(){
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.texture_id);
GL11.glMatrixMode(GL11.GL_TEXTURE);
GL11.glLoadIdentity();
GL11.glScalef(this.scale_width, this.scale_height, 1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
}

public void remove(){
IntBuffer texBuf = ByteBuffer.allocateDirect(4).asIntBuffer();
texBuf.put(this.texture_id);
texBuf.flip();
GL11.glDeleteTextures(texBuf);
}

private static final int next_power_of_two(int value){
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value++;
return value;
}

private static final boolean is_power_of_two(final int value){
return (value & (~value + 1)) == value;
}

private static final void set_wrap(final boolean horizontal, final Wrap_Mode wrap){
final int type = horizontal ? GL11.GL_TEXTURE_WRAP_S : GL11.GL_TEXTURE_WRAP_T;
switch (wrap){
case REPEAT :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_REPEAT);
break;
case MIRRORED_REPEAT :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL14.GL_MIRRORED_REPEAT);
break;
case CLAMP :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_CLAMP);
break;
case CLAMP_TO_BORDER :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL13.GL_CLAMP_TO_BORDER);
break;
case CLAMP_TO_EDGE :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL12.GL_CLAMP_TO_EDGE);
break;
}
}

private static final void set_filter(final boolean min, final Filter_Mode filter){
final int type = min ? GL11.GL_TEXTURE_MIN_FILTER : GL11.GL_TEXTURE_MAG_FILTER;
switch (filter){
case LINEAR :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_LINEAR);
break;
case NEAREST :
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, type, GL11.GL_NEAREST);
break;
}
}

public static enum Filter_Mode {
LINEAR, NEAREST;
}

public static enum Wrap_Mode {
REPEAT, MIRRORED_REPEAT, CLAMP, CLAMP_TO_BORDER, CLAMP_TO_EDGE;
}

private static final class TextureSizeException extends RuntimeException{
private static final long serialVersionUID = -8911712330468875206L;
public TextureSizeException(String string) {
super(string);
}
}
}
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on March 02, 2013, 09:44:05
Your program works for me, i will look into this and see what the difference between yours and mine is.
Thank you very much, this will be a great help.
Title: Re: Create a 2D Texture pixel data
Post by: Cornix on March 02, 2013, 12:10:55
Wow, i feel so stupid now. I really do.
As it seems the only problem was, that i forgot to enable 2D-Textures in my testing enviroment. T_T
All this trouble because of such a little mistake, i am sorry guys.

But thank you all, once again, for the awesome help.