PDA

View Full Version : Creating a texture from the front and backbuffer



cronodragon
31-10-2005, 01:19 AM
How can I create a texture from the front or back buffer? I'm using Clootie's DX9 headers.

The idea is to take a shot of the buffer in a texture, the process the texture with a pixel shader, and then place it in the buffer or draw it. What's the best method to acomplish that?

Regards!

Clootie
31-10-2005, 08:10 PM
First look for IDirect3DDevice9::StretchRect. You scan StretchRect from backbuffer (rendertarget) to rendertarget-texture. ANd on second step use this texture as the source to the shader drawn with full-screen quad.

Be warned: a lot of HW (probably except NV GF6 and up) have some restrictions on "non-power-of-two" textures.

cronodragon
01-11-2005, 12:20 AM
That's exactly what I was looking for. :D

cronodragon
01-11-2005, 03:50 PM
Ok, I made it this way:



procedure dx9_cScene.Draw;
const
FILTER_FORMAT = D3DFVF_XYZRHW or D3DFVF_TEX1;

FILTER: array[0..3] of TFilterVertex = (
(Pos: (x: 000.0; y: 480.0; z: 0.5; w: 1.0); Tex1: (x: 0.0; y: 1.0)),
(Pos: (x: 000.0; y: 000.0; z: 0.5; w: 1.0); Tex1: (x: 0.0; y: 0.0)),
(Pos: (x: 640.0; y: 480.0; z: 0.5; w: 1.0); Tex1: (x: 1.0; y: 1.0)),
(Pos: (x: 640.0; y: 000.0; z: 0.5; w: 1.0); Tex1: (x: 1.0; y: 0.0))
);

var
Texture: IDirect3DTexture9;
Backbuffer, Surface: IDirect3DSurface9;
VertexBuffer: IDirect3DVertexBuffer9;
Vertices: Pointer;

begin
if _Device = nil then Exit;

if Failed(D3DXCreateTexture(_Device, 512, 512, 1, D3DUSAGE_RENDERTARGET,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, Texture)) then Exit;
Texture.GetSurfaceLevel(0, Surface);

_Device.GetRenderTarget(0, Backbuffer);
_Device.SetRenderTarget(0, Surface);
_Device.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, _BackColor, 1.0,
0);

if Succeeded(_Device.BeginScene) then
begin
// Draw scene...

_Device.EndScene;
end;

if Failed(_Device.CreateVertexBuffer(SizeOf(FILTER), 0,
FILTER_FORMAT, D3DPOOL_DEFAULT, VertexBuffer, nil)) then Exit;
if Failed(VertexBuffer.Lock(0, SizeOf(FILTER), Vertices, 0)) then Exit;
CopyMemory(Vertices, @FILTER, SizeOf(FILTER));
VertexBuffer.Unlock;

_Device.SetRenderTarget(0, Backbuffer);
_Device.Clear(0, nil, D3DCLEAR_TARGET or D3DCLEAR_ZBUFFER, _BackColor, 1.0,
0);

if Succeeded(_Device.BeginScene) then
begin

_Device.SetTexture(0, Texture);
_Device.SetStreamSource(0, VertexBuffer, 0,
SizeOf(TFilterVertex));
_Device.SetFVF(FILTER_FORMAT);
_Device.DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

_Device.EndScene;
end;

_Device.Present(nil, nil, 0, nil);

Texture := nil;
Backbuffer := nil;
Surface := nil;
VertexBuffer := nil;
End;

It works, but I have 3 problems:
1) There is a blinking white rectangle at the top-left corner of the screen. I found out white is the default color of the filter mesh. Maybe it's not drawing that zone from time to time, and that's why it's blinking, but I don't know how to correct that.
2) A frame in the bottom of the screen is not being drawn, but it has the color of the scene background.
3) The textures of the models I load are getting corrupted, some triangles become white. This is really weird.

EDIT: I have just solved everything setting the texture size to 640x480 :


if Failed(D3DXCreateTexture(_Device, 640,480,...

Probably the Device was corrupting memory when trying to draw to a surface smaller than the one it was set for. :lol:

Clootie
01-11-2005, 08:51 PM
It was probably related to some interaction [driver bug ?] of different sizes of original (640x480) DepthBuffer and your new (512x512) renderTarget.
You can try to create and set new DepthBuffer with 512x512 size and assign at the same time with new renderTarget.

PS. Creating / destroying VertexBuffer each frame is REALLY BAD!

cronodragon
01-11-2005, 09:26 PM
It was probably related to some interaction [driver bug ?] of different sizes of original (640x480) DepthBuffer and your new (512x512) renderTarget.
You can try to create and set new DepthBuffer with 512x512 size and assign at the same time with new renderTarget.

Ok.


PS. Creating / destroying VertexBuffer each frame is REALLY BAD!

Really?! Hmm, I will create a global mesh for my filters. Thanks 8)

By the way, I found out that it's better to disable texture smoothing when creating those filters.