PDA

View Full Version : Rendering to a texture..



M109uk
15-01-2006, 12:37 PM
Hi all,

Im having problems rendering to a texture, the way that i understand it works is by:
1) creating a blank texture (initialization)
2) render the scene, and then copy it to the blank texture
3) render the scene

Create:

SetLength(Indexs, 1);

glEnable(GL_TEXTURE_2D);
glGenTextures(1, @Indexs[0]);
glBindTexture(GL_TEXTURE_2D, Indexs[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, Width, Height, 0);


Draw scene to texture:

If Textures[Texture] = Nil Then Exit;

glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

glViewport(0, 0, Textures[Texture].Width, Textures[Texture].Height);

glMatrixMode(GL_TEXTURE);
glLoadIdentity;
glMatrixMode(GL_MODELVIEW);

FollowTarget(Pos, Heading, Distance);

glBindTexture(GL_TEXTURE_2D, Indexs[0]);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height);

glViewPort(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);


I have bound got something wrong, all i get is a blank white texture :(

JSoftware
15-01-2006, 01:08 PM
You need to initialize the texture with glteximage2d(optionally with data set to nil) before you can call glcopyteximage2d.

Looking at your other code everything else seems to look fine

Paulius
15-01-2006, 01:13 PM
You need to initialize the texture with glteximage2d(optionally with data set to nil) before you can call glcopyteximage2d.
He bypases that with glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, Width, Height, 0); when creating.
White is what you usually get when texture state is invalid, you sure you're creating it before using? What if you replaced glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, Width, Height); with glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, Width, Height, 0);

Nitrogen
15-01-2006, 07:14 PM
Render to framebuffer textures are VERY buggy as I found out...

You also have to fill in the mipmap states (Even if you're not using mipmaps its usually a good idea to fully create the texture with mipmaps anyway)

Also the glTexImage2d() with the data argument set to nil can cause crashes on some systems, so I found out. So this is the code I used in my project:




// Note that FTarget is just set to GL_TEXTURE_2D.
// In the original code, it was also used with Cubemap textures too.

// Create a blank texture image first. It's handle is stored in FTexObject

glBindTexture(FTarget, FTexObject);

{ Create mipmap images too. This is to keep the texture from being
inconsistent at startup. Use GL_SGIS_generate_mipmaps to actually fill in
the mipmaps. }
i := 0;
mw := w;
mh := h;
done := FALSE;

try
Addtolog('Uploading mipmaps');
GetMem(Data, w*h*3);
ZeroMemory(Data, w*h*3);

while not done do
begin
if (mw = 1) and (mh = 1) then done := TRUE;
glTexImage2d(FTarget, i, 3, mw, mh, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
INC(i);
if mw > 1 then mw := mw shr 1;
if mh > 1 then mh := mh shr 1;
end;
glFinish;
finally
FreeMem(Data, w*h*3);
Data := nil;
end;


It's not pretty and you could probably get away with setting it to nil and not worrying about the glFinish command either, but this seems to work best for all the pc's its run on.

Clootie
15-01-2006, 11:06 PM
use FBO (with latest video drivers)

Paulius
16-01-2006, 11:43 AM
This is one area where DirectX is truly better than OpenGL, D3D had proper render to texture for ages and FBOs only work on GeForce4 Ti and up hardware.

JSoftware
16-01-2006, 02:01 PM
... and radeon 9500 and up.

Now the problem with your code is that you don't initialize the code correctly. You can't specify an internalformat with glcopyteximage2d. You need glteximage2d.

There's no idea in building mipmaps as he doesn't use any mipmap filtering. besides he can't mipmap textures which a copied from screen unless he has fbo's (glgeneratemipmapext)

Paulius
16-01-2006, 02:12 PM
Now the problem with your code is that you don't initialize the code correctly. You can't specify an internalformat with glcopyteximage2d. You need glteximage2d.
Why not? works for me

JSoftware
16-01-2006, 05:09 PM
Dammit paulius.. You got me there :oops:

I don't know why that works. My long time experiences tell me that people are always told to initialize their textures using glteximage2d.

Back on topic(now that i know that the code actually works :P ):
Have you checked that the texture id you are using is the same that you initialized. Have you checked viewport size? Have you checked to see what it renders when you copy to texture? have you textures disabled or set to something else before rendering?

M109uk
16-01-2006, 09:21 PM
The way it all works in my game is:
1) the textures class is created and then i create the blank texture (i have changed the creation class to:
[pascal]
SetLength(Indexs, 1);

glEnable(GL_TEXTURE_2D);
glGenTextures(1, @Indexs[0]);
glBindTexture(GL_TEXTURE_2D, Indexs[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
// (target: GLenum; level, internalformat: GLint; width, height: GLsizei; border: GLint; format, atype: GLenum; const pixels: Pointer);

Done := False;
i := 0;
Try
GetMem(Data, Width*Height*3);
ZeroMemory(Data, Width*Height*3);
While Not Done Do
Begin
If (Width = 1) And (Height = 1) Then Done := True;
glTexImage2d(GL_TEXTURE_2D, i, 3, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Data);
Inc(i);
If Width > 1 Then Width := Width Shr 1;
If Height > 1 Then Height := Height Shr 1;
End;
glFinish;
Finally
FreeMem(Data, Width*Height*3);
End;
[pascal]
I still seem to be getting the white texture..

2) during the rendering process, i call the procedure to update the texture
3) render the scene

* Im not sure if the texture id is set, i will check that now
* The viewport size doesnt seem to change, im constantly checking it during the rendering process to position elements.
* It supposed to render from the original camera, so im pretty sure that works
* I call glEnable(GL_Texture_2D) everytime i call the texture.bind procedure

tpascal
17-01-2006, 05:36 PM
Maybe it is stupid what i am going to say but...in your test what is the resulted width and heigh of the texture?, some videocards only accept power of 2 textures sizes; trying to create non power of 2 will result in just white color textures.

Also you have to check your device CAPS what it the maximun texture size allowed by your videocard.

good luck.

tp.

M109uk
17-01-2006, 08:22 PM
Hmm thats a good point... i forgot about that... i know my card doesnt take odd sized textures.. the texture size is set to the screen height and width, wich is set at 800 x 600