Creating textures

Hi, I’m trying to create a texture from a file and from a simple gridmap, a 100 x 100 array map of rgb byte values

but the problem is that the image is loaded to opengl but it gets distorted and with bad effects,

I’m using this:

to Create then image in opengl from a pointer to the image

CreateTexture(Width, Height, Format: Integer; Data:  Pointer): Integer;
var
  Texture: GLuint;
begin
  glGenTextures(1, @Texture);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  glBindTexture(GL_TEXTURE_2D, Texture);
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

  if Format = GL_RGBA
  then gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Width,  Height, GL_RGBA, GL_UNSIGNED_BYTE, pData)
  else gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData);

  result := Texture;
end;

and this to get the Imagedata from a file wich contains the pixel information like this:

R: Byte;
G: Byte;
B: Byte;

function CreateDSTextureFromData(Data: TTextureData): TDSImage;
var
  DataType, Size: Integer;
  Image:    Pointer;
begin
  Result.Width  := Length(Data.Data[0]);
  Result.Height := Length(Data.Data);
  DataType := Data.DataType;

  Size := Result.Width * Result.Height * DataType;
  GetMem(Image, Size);

  case DataType of
  3: Result.Texture := CreateTexture(Result.Width, Result.Height, GL_RGB, Image);
  4: Result.Texture := CreateTexture(Result.Width, Result.Height, GL_RGBA, Image);
  end;

  FreeMem(Image);
end

But it seems to doesn’t workd, is there any problem?

Thks for any help on this

What are you expecting it to do?

You are allocating some memory with

GetMem(Image, Size);

which could contain anything, then passing this to CreateTexture without filling it with any useful data.

Yes sorry, I forgot to sent the resto of the code:

the correct code is this:

and it still doesn’t work

function CreateDSTextureFromData(Data: TTextureData): TDSImage;
var
  DataType: Integer;
  Image:    Pointer;
  Size:     Integer;
begin
  Result.Width  := Length(Data.Data[0]);
  Result.Height := Length(Data.Data);
  DataType := Data.DataType;

  Size := Result.Width * Result.Height * DataType;
  GetMem(Image, Size);
  Image := @Data.Data; <- is this right?

  case DataType of
  3: Result.Texture := CreateTexture(Result.Width, Result.Height, GL_RGB, Image);
  4: Result.Texture := CreateTexture(Result.Width, Result.Height, GL_RGBA, Image);
  end;

  FreeMem(Image);
end;

and the structure of the Data:

TTextureData = record
DataType: Integer; <- pixel format
Data: array of array of TRGBA;
end;

and is all the rest right?

thks again

This is even worse now:

GetMem(Image, Size);
Image := @Data.Data; <- is this right?
*call CreateTexture*
FreeMem(Image);

You are allocating Size bytes, and storing the pointer to this value in “Image”, then immediately overwriting this pointer with a pointer to the multidimensional dynamic array “Data.Data”. Then later you call FreeMem + try to free Size bytes from where “Image” is pointing, which is from “Data.Data”. This will most likely cause your program to die horribly.

As well as dangerous calls to GetMem/FreeMem, you don’t seem to understand how Delphi’s dynamic arrays work, a dynamic array is a pointer to the array data, with hidden fields at a negative offset to the start of the data, containing the length of the array + the reference count. Using a dynamic array of dynamic arrays: eg.

Data: array of array of TRGBA;

Will not provide you with a chunk of memory that is consecutive, but will create an array of pointers to the dynamic arrays that contain each row. Each row could be a different length too. Using @Data.Data will provide a pointer to the start of this array of pointers.

The best solution would probably be to define TTextureData as using a 1D dynamic array to store the image data, with an extra Width + Height field:

TTextureData = record
DataType: Integer; <- pixel format
Width, Height: Integer;
Data: array of TRGBA; //or array of byte
end;
function CreateDSTextureFromData(Data: TTextureData): TDSImage;
var
  DataType: Integer;
  Image:    Pointer;
  Size:     Integer;
begin
  Result.Width  := Data.Width;
  Result.Height := Data.Height;
  DataType := Data.DataType;

  Image := @Data.Data;

  case DataType of
  3: Result.Texture := CreateTexture(Result.Width, Result.Height, GL_RGB, Image);
  4: Result.Texture := CreateTexture(Result.Width, Result.Height, GL_RGBA, Image);
  end;
end;

If you don’t want to move from a multidimensional dynamic array, then each time you want to interact with OpenGL, you will need to copy each row of your image data into a temporary buffer that does contain the data in one consecutive chunk of memory, which is probably why someone suggested the GetMem/FreeMem approach.

Thanks, I didn’t know how to work with these vars, and yes, I use a multidimensional array, but my problem is to set the poiter correctly, I’m still starting to work with them

but I’ve tried to convert to a simple array of TRGB using this:

  for y := 0 to Image.Height-1 do
  begin
    Line := Image.ScanLine[y];
    for x := 0 to Image.width-1 do
    begin
      i := y * Image.width + x;
      Result.Data[i] := Line[x];
    end;
  end 

and this:

Image := @Data.Data;

  case DataType of
  Result.Texture := CreateTexture(Result.Width, Result.Height, GL_RGB, Image);

but it still don’t work, I’m getting mad with this, is there anything wrong? is there a way that I can send you the code?

thanks again for the time

I just don’t know how the texture data should be passed to opengl

It must e in one simple array of pixel data with the height and width information only?

Can it work with 2d arrays?

thks