DX Render to image

BlitzMax Forums/BlitzMax Programming/DX Render to image

tonyg(Posted 2006) [#1]
This is really getting annoying.
I want to render to an image a la imagebuffer.
I've got it working... kind of.
There's a lot of problems but, as it stands, the resulting image is tiny.
I did read once that this would happen (some DX7 tutorial) but it didn't say how to resolve it.
Uncomment everything in the mainloop as it works BUT you have to escape quickly to actuqally grab the image before it disappears... for some reason.
Comment out the drawoval (notice it's parms are 0,0,0,0) and the resulting image is even smaller.
Any ideas?
Strict
Graphics 640,480
Local image1:TImage=LoadImage("man.png") 
Local image2:TImage=LoadImage("body.png")
' Because Bmax users DX Texture Manager it is necessary to create a dummy rendertarget surface
' and then blit from that surface to the image surface.
'Global mysurf:IDirectDrawSurface7   ' The dummy surf to be used as the rendertarget.
'While Not KeyHit(KEY_ESCAPE)
   Local mysurf:IDirectDrawSurface7=render2image_start(image1)   ' set image1 as the destination image for the draw
   DrawImage image2,0,0 
   DrawOval 0,0,0,0
   render2image_stop(image1,,mysurf)    ' stop rendering to the image and reset to the backbuffer
'   Cls
'   SetBlend maskblend
'   SetAlpha 1.0
'   DrawImage image1,0,0         ' draw the new image
'   DrawText GCMemAlloced(),0,300
'   Flip
'Wend
Cls
DrawImage image1 , 0 , 0
DrawText ImageWidth(image1) + " " + ImageHeight(image1),100,100
Flip
WaitKey()
Function render2image_start:IDirectDrawSurface7(image:TImage , frame:Int = 0)
'	mysurf.release_()
	Local mypix:TPixmap=LockImage(image)  ' lock the image to obtain a pixmap.
    Local mysurf:IDirectDrawSurface7=createsurffrompixmap(mypix)  ' Create the rendertarget surface
	Local res=PrimaryDevice.Device.SetRenderTarget(mysurf,0)  ' set the new surface as the rendertarget.
	If res<>DD_OK RuntimeError "D3D7Max2D Rendertarget failed" ' Check it worked OK.
	Cls  ' Clear the rendertarget
	DrawImage image , 0 , 0 'need to copy the 'destination' image to the render surface.
	Return mysurf
End Function
Function render2image_stop(image:TImage,frame=0,mysurf:IDirectDrawSurface7)
    ' Set the src and dest sizes to copy from/to. Thought I could leave these null but it produces horrid results.
    ' These parms could be used to copy a part of an image to another.
	Local src[]=[0,0,ImageWidth(image),ImageHeight(image)]  	
	Local dest[]=[0,0,ImageWidth(image),ImageHeight(image)]  
	dest[2]:+dest[0]
	dest[3]:+dest[1]
	' Do the blit from the dummy rendertarget to the image surface.
	TD3D7ImageFrame(image.frame(frame)).surface.Blt dest,mysurf,src,0,Null
	' Release the surface
	mysurf.release_()
	' reset rendering to the backbuffer
    render2backbuffer()
End Function
Function render2backbuffer()
    'set the rendertarget to the backbuffer
   	PrimaryDevice.Device.SetRenderTarget PrimaryDevice.backbuffer,0
End Function
Function createsurffrompixmap:IDirectDrawSurface7(temppix:TPixmap)
'lifted and butchered from Bmax source.
' I Don't use the POW2SIZE in this case.
		Function Pow2Size( n )
			Local t=1
			While t<n
				t:*2
			Wend
			Return t
		End Function
		Local 	surf:IDirectDrawSurface7  ' The dummy surface to return as the rendertarget
		Local	desc:DDSURFACEDESC2=New DDSURFACEDESC2  ' the 'description' of the surface
		Local	res   ' Used to hold the return code of DX operations.
		desc.dwSize=SizeOf(desc)  ' size of the description 
		desc.dwFlags=DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_PITCH   'Something to do with valid members?
		desc.dwWidth=temppix.width   ' Width of the surface = to the pixmap width
		desc.dwHeight=temppix.height ' Same but for height.
		desc.lPitch=temppix.pitch  ' Think this is for pixmap memory location
		desc.lpSurface=temppix.pixels ' and this
		desc.ddsCaps=DDSCAPS_3DDEVICE|DDSCAPS_VIDEOMEMORY  ' Surface can be rendered to and held in videomem.
		desc.ddpf_dwSize=SizeOf(DDPIXELFORMAT)
		Select temppix.format
			Case PF_BGR888
				desc.ddpf_dwFlags=DDPF_RGB
				desc.ddpf_BitCount=24
				desc.ddpf_BitMask_0=$ff0000
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$0000ff
			Case PF_RGB888
				desc.ddpf_dwFlags=DDPF_RGB
				desc.ddpf_BitCount=24
				desc.ddpf_BitMask_0=$0000ff
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$ff0000
			Case PF_BGRA8888
				desc.ddpf_dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS
				desc.ddpf_BitCount=32
				desc.ddpf_BitMask_0=$ff0000
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$0000ff
				desc.ddpf_BitMask_3=$ff000000
			Case PF_RGBA8888
				desc.ddpf_dwFlags=DDPF_RGB|DDPF_ALPHAPIXELS
				desc.ddpf_BitCount=32
				desc.ddpf_BitMask_0=$0000ff
				desc.ddpf_BitMask_1=$00ff00
				desc.ddpf_BitMask_2=$ff0000
				desc.ddpf_BitMask_3=$ff000000
		End Select	
		' Create the surface and return the result into RES	
		res=PrimaryDevice.DDraw.CreateSurface( desc,Varptr surf,Null )
		If res<>DD_OK RuntimeError "D3D7Max2D Create System Surface Failed"
		Return surf		
End Function



smilertoo(Posted 2006) [#2]
indiepath released a render to texture module.


tonyg(Posted 2006) [#3]
I know. It didn't actually save the texture back into the image.


smilertoo(Posted 2006) [#4]
It didnt what?

I tried it out and it was rendering to the textures i had.


tonyg(Posted 2006) [#5]
It renders to a new image rather than take an existing image and render to it.
I want to write the changes back into an image loaded using loadimage with out having to grabpixmap, memcopy etc.
I could be very wrong but when I checked with Tim I never got a response.
In fact, if you refer back to 'myimage' it has the same size issue that I get.


ImaginaryHuman(Posted 2006) [#6]
How about render one image to backbuffer, render other image on top of it, then grabimage back into the original image, do a cls, then draw.


tonyg(Posted 2006) [#7]
You know this has come up many times before and, rather than better to use grabpixmap, there would be too many for multiple frames of animation.
Anyway, as per the other topic , I'll find a way.


ImaginaryHuman(Posted 2006) [#8]
grabimage should be faster than grabpixmap, or at least glcopytexsubimage2d is faster because it grabs into a preexisting image.