PDA

View Full Version : Noise texture generator



Mrwb
27-03-2004, 11:21 PM
I'm trying to do a texture generator using OpenGl.
The thing I can't seem to get right, is manipulating the pData in gluBuild2DMipmaps which I use to build a bitmap of the generated texture.
I tried using some code I found here on DGDev to do the noise, but this
was rather unsuccesfull since the code uses scanline.
Currently, it throws me an access violation. (of course, even I can see that
it wont work;))

So I have a procedure to do the bitmap building of the data pointer, but
have no idea how to get the data pointer right.


type
TRGBArray = array[0..MAXPIXELS - 1] of TRGBTriple;
pRGBArray = ^TRGBArray;

type
TGeneratedTexture=class
private
public
pTextureData: pointer;
Texture: glUint;
procedure GenerateTexture;
procedure AddNoise(R,G,B: byte);
procedure AssignData(Data: pointer);
procedure GetColor(Color: byte);
procedure Bind;
end;

procedure TGeneratedTexture.AddNoise(R,G,B: byte);
var
pData: pRGBArray;
J,I: integer;
begin
for J := 0 to TEXHEIGHT - 1 do
begin
for I := 0 to TEXWIDTH - 1 do
begin
pData[I].rgbtRed:=Random(R);
pData[I].rgbtGreen:=Random(G);
pData[I].rgbtBlue:=Random(B);
end;
pTextureData:=pData;
GenerateTexture;
end;
end;

procedure TGeneratedTexture.GenerateTexture;
begin
glGenTextures(1, Texture);
glBindTexture(GL_TEXTURE_2D, Texture);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TEXWIDTH, TEXHeight, GL_RGB, GL_UNSIGNED_BYTE, pTextureData);
end;

Paulius
28-03-2004, 09:42 AM
You have to make a pointer point somewhere before trying to write to memory through it, and your GenerateTexture call is in a for J := 0 to TEXHEIGHT ?_" 1 loop. It should look something like this:

procedure TGeneratedTexture.AddNoise(R, G, B: byte);
var
pData: PRGBTriple;
j, i: integer;
begin
GetMem(pData, TEXHEIGHT * TEXWIDTH * SizeOf(TRGBTriple));
pTextureData:= pData;
for j := 0 to TEXHEIGHT - 1 do
for I := 0 to TEXWIDTH - 1 do
begin
pData.rgbtRed:= Random(R);
pData.rgbtGreen:= Random(G);
pData.rgbtBlue:= Random(B);
inc(pData, SizeoOf(TRGBTriple));
end;
GenerateTexture;
Dispose(pTextureData);
end;

Mrwb
28-03-2004, 01:33 PM
Thanks for the relpy! :)
I actually didn't notice that the GenerateTexture call was inside the J loop :oops: Oh well.. Anyway, the code above also throws an access violation when trying to write to memory.
Pointers make my head hurt. ;)

Paulius
28-03-2004, 07:11 PM
A bit of an oversight, inc in the loop should be by 1 instead of SizeoOf(TRGBTriple).

Mrwb
28-03-2004, 07:57 PM
Thanks! works excellent now :)

Mrwb
28-06-2004, 04:30 PM
I was just wondering, whats the best way to apply operators to textures created this way? (IE: combining textures and applying distortion)

Paulius
29-06-2004, 01:09 PM
The best and simplest way is to not do anything with textures but with data you are generating textures with, storing that data in a 2D array should save you some sanity.

Mrwb
29-06-2004, 07:58 PM
Thanks for the tip ;) I've allready implemented arrays.
I did it like this:

Pixel/shader creator example (woks perfect):
(t3arr is just a record containing r,g,b bytes)


const
TEXWIDTH=256;
TEXHEIGHT=256;

type
TextureItem=record
Data: Pointer;
Texture: gluInt;
Raw: array[0..255,0..255] of T3Arr;
end;

function GetPixelShape(X,Y: byte):byte;
var
x2,y2,radius,baseradius,temp: extended;
begin
x2:=128;
y2:=128;
radius:=Sqrt(power((x2-x),2)+power((y2-y),2));
baseradius:=Sqrt(power((x2-30),2)+power((y2-128),2));
if radius<=baseradius then
Result:=255-trunc(2.5*radius)
else
Result:=0;
end;

procedure Pixel(LayerNumber: integer; Grid: byte);
var
pData: pRGBTriple;
j, i: integer;
temp: integer;
F: boolean;
begin
if Grid=1 then
F:=true
else
F:=false;
GetMem(pData, TEXHEIGHT * TEXWIDTH * SizeOf(TRGBTriple));
FTextures[LayerNumber].Data:= pData;
for j := 0 to TEXHEIGHT - 1 do
for I := 0 to TEXWIDTH - 1 do
begin
Temp:=GetPixelShape(I,J);
if f=false then //don't draw with grid
begin
case FCurrentOperator of
0: //Overwrite
begin
FTextures[LayerNumber].Raw[J,I].r:=temp;
FTextures[LayerNumber].Raw[J,I].g:=temp;
FTextures[LayerNumber].Raw[J,I].b:=temp;
end;
1: //Add
begin
if temp<>0 then
begin
FTextures[LayerNumber].Raw[J,I].r:=trunc((FTextures[LayerNumber].Raw[J,I].r /2)+(temp/2));
FTextures[LayerNumber].Raw[J,I].g:=trunc((FTextures[LayerNumber].Raw[J,I].g /2)+(temp/2));
FTextures[LayerNumber].Raw[J,I].b:=trunc((FTextures[LayerNumber].Raw[J,I].b /2)+(temp/2));
end;
end;
end;
pData.rgbtRed:= FTextures[LayerNumber].raw[J,I].r;
pData.rgbtGreen:= FTextures[LayerNumber].raw[J,I].g;
pData.rgbtBlue:= FTextures[LayerNumber].raw[J,I].b;
end
else //draw with grid
if (odd(i)) and (odd(j)) then
begin
FTextures[LayerNumber].Raw[J,I].r:=0;
FTextures[LayerNumber].Raw[J,I].g:=0;
FTextures[LayerNumber].Raw[J,I].b:=0;
pData.rgbtRed:= 0;
pData.rgbtGreen:= 0;
pData.rgbtBlue:= 0;
end
else
begin
case FCurrentOperator of
0: //overwrite
begin
FTextures[LayerNumber].Raw[J,I].r:=temp;
FTextures[LayerNumber].Raw[J,I].g:=temp;
FTextures[LayerNumber].Raw[J,I].b:=temp;
end;
1: //add
begin
if temp<>0 then
begin
FTextures[LayerNumber].Raw[J,I].r:=trunc((FTextures[LayerNumber].Raw[J,I].r /2)+(temp/2));
FTextures[LayerNumber].Raw[J,I].g:=trunc((FTextures[LayerNumber].Raw[J,I].g /2)+(temp/2));
FTextures[LayerNumber].Raw[J,I].b:=trunc((FTextures[LayerNumber].Raw[J,I].b /2)+(temp/2));
end;
end;
end;
pData.rgbtRed:=FTextures[LayerNumber].Raw[J,I].r;
pData.rgbtGreen:=FTextures[LayerNumber].Raw[J,I].g;
pData.rgbtBlue:=FTextures[LayerNumber].Raw[J,I].b;
end;
inc(pData, 1);
end;
end;



However, I've had some problems getting my blending procedure right, which was the reason for my question:


procedure CombineTextures(src1,src2,dest: integer);
var
pData: pRGBTriple;
j, i: integer;
temp: byte;
begin
GetMem(pData, TEXHEIGHT * TEXWIDTH * SizeOf(TRGBTriple));
FTextures[dest].Data:= pData;
for j := 0 to TEXHEIGHT - 1 do
for I := 0 to TEXWIDTH - 1 do
begin
FTextures[Dest].raw[J,I].r:=trunc((FTextures[src1].Raw[J,I].r/2)+((FTextures[Src2].Raw[J,I].r / 2)));
FTextures[Dest].raw[J,I].g:=trunc((FTextures[src1].Raw[J,I].g/2)+((FTextures[Src2].Raw[J,I].g / 2)));
FTextures[Dest].raw[J,I].b:=trunc((FTextures[src1].Raw[J,I].b/2)+((FTextures[Src2].Raw[J,I].b / 2)));

pData.rgbtRed:=FTextures[Dest].raw[J,I].r;
pData.rgbtGreen:=FTextures[Dest].raw[J,I].g;
pData.rgbtBlue:=FTextures[Dest].raw[J,I].b;
inc(pData, 1);
end;
end;

Paulius
29-06-2004, 08:51 PM
Whoa, you do not need to duplicate texture data, do your operations with the array and when you want to use a pointer simply get the address of the first element of the array. You're procedure is missing a begin

Mrwb
29-06-2004, 10:25 PM
Hehe. the begin must have been lost when I formated the text. As for not needing to dublicate my data, I guess you're right, but my understanding of pointers are nothing but confusing ;) Will do though. :)

I still can't figure out whats wrong with the blending though. Oh well, I think I'll find the problem eventually ;)

Paulius
30-06-2004, 09:50 AM
Can't see anything bad, perhaps the problem lies elsewhere, what exactly goes wrong? Pointers are simply variables which hold memory addresses, from what you posted you can remove all you're pointer operations at all, and for stuff that wants a pointer to the beginning of texture data like gluBuild2DMipmaps simply do @FTextures[LayerNumber].Raw[0,0] (@ before a variable gets it's addres).

Mrwb
30-06-2004, 02:47 PM
It simply copies the src1 texture.. :?

Paulius
30-06-2004, 04:55 PM
For it to be a copy Src1 and Src2 must be the same or have the same data because you divide each one by two, something is mixed up outside of this procedure

Mrwb
30-06-2004, 07:36 PM
I just removed all pointer stuff like you suggested, I thought maybe that was the root of the probelem. But still the src1 is copied. The wierd thing is that blending works in the other functions. IE; if you apply several operations on a texture like Pixel, Gradient etc. it combines them given that your operator is set to 1.

EDIT: I found the problem.. :oops: omg am I stupid or what? The textures are created with a script read from a string array that goes like this:

SelectTexture(0)
Pixel(0)
CreateTexture

etc.

The combine command, looks like this Combine(src1,Src2) the problem was I forgot to register the second parameter in the command parser.. :oops: