2 questions regarding surfaces

Started by
13 comments, last by MannyCalavera 19 years, 8 months ago
Quote:Original post by Nik02
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.


Woah, this information will come in handy. :) Thanks.

Quote:Original post by Nik02
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.


Ok, so I'll have to look out to prevent unnecessary locking.

Quote:Original post by Nik02
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.


Well, I'm not entirely sure how to do this. I can create a rectangle and texture it so far and I also know how to show it on the screen. What I didn't understand yet is how to use surfaces as RenderTargets (all my tries with Device.CreateRenderTarget didn't work out like I hoped). If you could give me a quick push in the right direction I would be very happy. :)

Quote:Original post by Nik02
Please ask for more info if needed.


Thanks for the kind offer. I just did. :)

And thanks again for the great help and all the information.
Advertisement
Sorry for the late reply - gdnet was down for a moment. Anyway, a quick, but not by any means concise course on render targets:

When you create a texture using IDirect3DDevice9::CreateTexture, you can specify an usage flag, D3DUSAGE_RENDERTARGET to create a render target texture (preferably in DEFAULT pool, ie. video memory - I don't remember if this was mandatory or not). Then, at render time, you do the following:


  • Save the pointer to the original back buffer, for example's sake let's name it pOrigBackBuffer.
  • Set the previously created texture's level 0 surface as the current rt by calling pDev->SetRenderTarget(0,pRt->GetSurfaceLevel(0)).
  • Optionally, set a new depth stencil surface here, using pDev->SetDepthStencil(...) passing a previously created depth stencil surface pointer to the function. Note that in case you do this, you need to save the previous depth stencil as well, as we did to the original back buffer in step 1.
  • pDev->Clear (as necessary); pDev->BeginScene(); -Render whatever you want to the texture-; pDev->EndScene();
  • Restore the original render target using the back buffer pointer saved in step 1. Optionally, do this for the depth stencil also, if you changed it.
  • pDev->Clear (as necessary); pDev->BeginScene(); -Render whatever you want to the frame buffer a.k.a. back buffer this time around-; pDev->EndScene();
  • pDev->Present()


Do note that the default back buffer, by definition, is a render target - so you can draw two triangles to it simply by using DrawPrimitive* functions. Now, if you set a texture with alpha channel on the device, the texture will be subsequently used in all drawing operations until it is changed again. Finally, you need to set alpha blending related renderstates to actually instruct the hardware to blend the source and destination - finding out which, I leave as an excercise to the reader (hint: this is a very common topic here).

-Nik

EDIT: I should mention, "Drawing two textured triangles (to form a quad)" is exactly what the sprite interface encapsulates.

Niko Suni

Quote:Original post by Nik02
Sorry for the late reply - gdnet was down for a moment.


No problem at all. I have to excuse myself for the late answer now too. I'm changing residence (is this proper english?) in the moment and usually haven't much time for the internet at the weekend.

Thanks for the very complete rundown on how to do this things. I'm a bit emberrased but I already have problems with the first step.

Quote:Original post by Nik02

  • Save the pointer to the original back buffer, for example's sake let's name it pOrigBackBuffer.




All others seem clear to me but I don't know how to get the pointer to the Backbuffer. I didn't find a function which provides me with the backbuffer.

But I tried a bit around already and I created a textured quad to paint a transparent pic to the backbuffer with renderstates and all. So my only problem left is drawing this quad to the offscreen-surface and there my only problem will be the pointer to the backbuffer (I hope ;) ).

Thanks (again)
Without your help I would be really stuck. :)
IDirect3DDevice::GetBackBuffer() will retrieve a pointer to the currently set backbuffer. Note that when you do change it, the function subsequently returns the new backbuffer, not (necessarily) the original one - that's the reason you must save the original backbuffer pointer manually before changing the render target to your own rt surface.

Niko Suni

Oh well "GetBackBuffer". I should have seen this. :) Thanks for all your help (and all the handy extra information). I'll have a look at this now.

This topic is closed to new replies.

Advertisement