2 questions regarding surfaces

Started by
13 comments, last by MannyCalavera 19 years, 8 months ago
Hi, I played around with surfaces and stuzmbled upon 2 problems. What I want to do is in short the following: 1) Put a picture on surface1 2) Put a picture on surface2 3) Put a part the picture on surface 1 on surface 2 4) Create a texture and use surface 2 to fill it 5) Paint this texture on a sprite 6) Paint this sprite on the screen So well, some steps may seem strange but there is a bit learning involved for me here and I think this are some things I just have to know. Now my source: Preperation, only executed once:

  //1.) Put a picure on Surface1
    Device.CreateOffscreenPlainSurface(500, 500, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, Surface1, nil);
    D3dXLoadSurfaceFromFile(Surface1, nil, nil, 'd:\fish.png', nil, D3DX_DEFAULT, 0, nil);

  //2.) Put a picure on Surface1
    Device.CreateOffscreenPlainSurface(500, 500, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, Surface2, nil);
    D3dXLoadSurfaceFromFile(Surface1, nil, nil, 'd:\house.bmp', nil, D3DX_DEFAULT, 0, nil);

  //Create Picture 3 which I need later for drawing to the screen (I think)
    Device.CreateOffscreenPlainSurface(500, 500, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, Surface3, nil);

Render Loop:

    Clear(D3DCOLOR_XRGB(0, 0, 0));
    BeginScene;

  //3) Put a part the picture on surface 1 on surface 2
    rect.Left := 0;
    rect.Top := 0;
    rect.Right := 100;
    rect.Bottom := 100;
    Device.StretchRect(Surface11, @rect, Surface2, @rect, D3DTEXF_NONE);

  //4) Create a texture and use surface 2 to fill it
    D3DXCreateTexture(Device, 500, 500, D3DX_DEFAULT, D3DUSAGE_RENDERTARGET,  D3DFMT_X8R8G8B8,D3DPOOL_DEFAULT, Texture1);
    Texture1.GetSurfaceLevel(0, Surface3);

  //5) Paint this texture on a sprite

    D3DXLoadSurfaceFromSurface(Surface3, nil, nil, Surface2, nil, nil, D3DX_DEFAULT, 0);
  D3DXCreateSprite(Device, Sprite1);

  //6) Paint this sprite on the screen
      Sprite.Draw(Texture1, nil, nil, nil, 0, nil, 0);
  //Well, this doesn't work.

    EndScene;
    Pressent(nil, nil, 0, nil);

My 2 problems are: 1) Nr. 5 is awfully slow, so damn slow I can't believe it's in anyway hardware-enhanced. Do I do anything wrong? 2) How do I paint this Sprite now to the screen? Well, I hope this questions aren't to hard to understand. Maybe someone can help me. Pleeeeaaase. Thanks in advance. Edited by Coder: Use source tags. Check GDNet Forums FAQ [Edited by - Coder on August 20, 2004 6:38:13 AM]
Advertisement
Well, no posts yet. :(

Did I explain my problem to complicated or chaotic? It's a bit hard since english isn't my native language.
I think what you are trying to accomplish is to draw a part of an image to the screen?
GBS
Summed up, that's right. But I want to do some things to the image I want to draw before rendering. That's why I used the OffscreenSurfaces.

In fact, I want to use the surfaces like I used TBitmap in ancient times ;). As a kind canvas in memory, to which i draw and where I can compose a picture out of some more and in the end I want to draw the result to the screen.
allright, why step 5 is slow: you are loading a surface. That is very slow. Why are you cpoying the surface to another? 2 -> 3.

I'm not so into the whole d3dxsprite thing so for that you need someone else sorry.

GBas
GBS
Thanks so far.

Quote:Original post by GraphicsBas
allright, why step 5 is slow: you are loading a surface. That is very slow. Why are you cpoying the surface to another? 2 -> 3.


Well, I realized that it's slow. I'm open to any ideas to make it faster. :)
With the copying itself I try to accomplish the following:

1)Surface 1 loads a picture
2) Surface 2 loads a picture
3) Draw some Parts of the picture in surface 1 to surface 2
4) Draw the altered surface 2 to the screen

If there is another, better, faster way to do this I would be glad to hear it. :)

Quote:Original post by GraphicsBas
I'm not so into the whole d3dxsprite thing so for that you need someone else sorry.


No problem at all :)
I'm just learning it myself.
First you should create a texture and retrieve the 0 surface and name it surface 3. This is done in an initialize function.

In the render loop you just draw surface 2 to surface 3. Then you can draw parts of surface 1 to surface 3. Now you have in the texture the part you want to render.

I believe this should work... (edit: and fast :))

GBas
GBS
To access a d3d surface's internal color data generally, you need to lock it to get a pointer to the raw pixel data, and unlock it when done with the data for the graphics device to gain access to it again.

However, there are many helper functions built in D3D for most common blitting operations:


  • IDirect3DDevice9::StretchRect - copies between surfaces in video memory. Can stretch data while copying, depending on the relevant hardware capabilities.
  • IDirect3DDevice9::UpdateSurface - uploads a system memory surface to video memory. No stretching; this is meant as a high-performance function. You can still specify the rectangle to copy, though.
  • IDirect3DDevice9::UpdateTexture - this function suits better for texture uploading, because it handles the mipmap levels if applicable, and also takes care of cube and volume textures.

D3DX contains more robust (read: more convenient) functions for these purposes, including but not limited to D3DXFillTexture, D3DXFilterTexture, D3DXLoadSurfaceFromSurface etc.

-Nik

EDIT: By the way, in d3d it is much more efficient to draw two triangles with a source image as the texture, than it is to copy the pixel data by manually locking the surfaces. 3d accelerator hardware is specifically designed to draw textured geometry, not moving large chunks of data from the graphics bus.

Niko Suni

@GraphicsBas

Thanks alot. It seems to be very fast now. :) Yippeah!

But my drawn texture is totally garbled. To change the format seems also to change the garbleness (is this even a word? :D ). Are there only specific formats to use with textures?

Edit: Seems it was my hardware, my card doesn't like anispotric filtering. :D

Quote:Original post by Nik02

  • IDirect3DDevice9::StretchRect - copies between surfaces in video memory. Can stretch data while copying, depending on the relevant hardware capabilities.
  • IDirect3DDevice9::UpdateSurface - uploads a system memory surface to video memory. No stretching; this is meant as a high-performance function. You can still specify the rectangle to copy, though.
  • IDirect3DDevice9::UpdateTexture - this function suits better for texture uploading, because it handles the mipmap levels if applicable, and also takes care of cube and volume textures.



Thanks for the list. Something like that is alwas good for newbies (like me). :)

Quote:Original post by Nik02
D3DX contains more robust (read: more convenient) functions for these purposes, including but not limited to D3DXFillTexture, D3DXFilterTexture, D3DXLoadSurfaceFromSurface etc.


Is more convenient == slow in any cas when I use these (my try with LoadSurfaceFromSurface was damn slow)? :)

Quote:Original post by Nik02
EDIT: By the way, in d3d it is much more efficient to draw two triangles with a source image as the texture, than it is to copy the pixel data by manually locking the surfaces. 3d accelerator hardware is specifically designed to draw textured geometry, not moving large chunks of data from the graphics bus.


I always thought locking was only required when I change vertices diffuse colors and so (I did some pure 3d-programming before I took the ID3DXSprites). Is it necessary as long as I use this functions?

Thanks you 2, I think slowly but surely things become more clear.

Edit:

Something more:

I tried it as GraphicsBas suggested, but the alphachannel of the part of surface 1 which I drew on surface 3 seems to clear the underlying pixels (from surface 2).

Do you know of any problems with alphachannels and this kind of "surface-compositing"?

Thanks in advance

[Edited by - MannyCalavera on August 20, 2004 5:44:13 AM]
Quote:Original post by MannyCalavera
Is more convenient == slow in any cas when I use these (my try with LoadSurfaceFromSurface was damn slow)? :)


LoadSurfaceFromSurface is relatively slow, if it has to filter the data or format conversion is required. If both the source and destination are of exactly same size and format, then the function, as far as I know, performs a direct blit and that is fast. Remember: if you want to stretch the data with your own function, it will have to do the same steps anyway.

Quote:
I always thought locking was only required when I change vertices diffuse colors and so (I did some pure 3d-programming before I took the ID3DXSprites). Is it necessary as long as I use this functions?


Any function that moves data between d3d resources have to lock the said resources, be it manually or internally by d3d. The functions that I listed do lock the resources, but it is transparent to the programmer. Nevertheless, any type of lock should be avoided unless necessary, because it may stall the rendering pipe - as the hw cannot do anything with the locked data before it is unlocked.

Quote:
I tried it as GraphicsBas suggested, but the alphachannel of the part of surface 1 which I drew on surface 3 seems to clear the underlying pixels (from surface 2).

Do you know of any problems with alphachannels and this kind of "surface-compositing"?


The surface transfer functions do not perform alpha-blending; instead, they just overwrite the destination alpha values with the source alpha values.

If you want to do alpha blending, you need to render some geometry (a quad, for example) with the texture containing the alpha values to the destination surface (which must be designated as a render target). Of course, you could also manually lock the surfaces, and do software blending on them, but that is usually orders of magnitude slower than the equivalent hardware procedure.

Please ask for more info if needed.

Kind regards,
-Nik

Niko Suni

This topic is closed to new replies.

Advertisement