VideoTexture - Is there anyway to copy a texture from one to another?

I want a videotexture to copy from another videotexture to save the previous rendered image for current frame, but when I do this:


g.tex2.refresh(True)
g.tex.refresh(True)

it results the same texture :spin:

my videotexture setup:


g = bge.logic

   g.tex = bge.texture.Texture(own, 0, 0)             
    g.tex.source = bge.texture.ImageRender(scene, cam)
    g.tex.source.capsize = [512, 512]
    
    g.tex2 = bge.texture.Texture(own, 0, 1)            
    g.tex2.source = g.tex.source
    g.tex2.source.capsize = [512, 512]  

[I think it is strange to store data that belongs to an object in the logic module. Must be the influence of the example in the API documentation. ;)]

Texture Source

It might not that obvious because you hide it in a lot of qualifications. You use the exact same object for both.

Lets remove the unnecessary data and rename it a bit:


texture = bge.texture.Texture(own, 0, 0)   
texture.source = bge.texture.ImageRender(scene, cam)
texture.source.capsize = [512, 512]
   
anotherTexture = bge.texture.Texture(own, 0, 1)            
anotherTexture.source = texture.source
anotherTexture.source.capsize = [512, 512] # guess what is strange on that line?

You still not see it?

Lets isolate the operations a bit more and change the processing order:


imageSource = bge.texture.ImageRender(scene, cam)
imageSource.capsize = [512, 512]

texture = bge.texture.Texture(own, 0, 0)   
anotherTexture = bge.texture.Texture(own, 0, 1)            

texture.source = imageSource
anotherTexture.source = imageSource 

(Guess where the last line from previous code snippet is?)

Refresh

To get the effect you really want to achieve (showing the previous source) I guess you should think about what refresh() is doing.

According to the BGE API there are two different refresh(:

  • Source refresh() which invalidates the current content (in case of ImageFFmpeg it loads the image again).
    *Texture refresh is a bit unclear what exactly it does, I guess it transfers the buffer of the current source to the texture of the mesh. If the first argument is true it calls source.refresh() beforehand that you do not need to explicitly call it from your code.

This means:


texture.refresh(True)
anotherTexture.refresh(True)

does four operations:

  1. (implicit because of True) invalidates imageSource [and loads the image to it]
  2. updates the meshes texture of texture
  3. (implicit because of True) invalidates imageSource [and loads the image to it]
  4. updates the meshes texture of anotherTexture

As both textures are fed by the same source your load the same image twice. I guess you get the same result when running:


texture.refresh(True)
anotherTexture.refresh(False)

[Hint: texture.refresh(True) == texture.refresh()]

Copy from another videotexture

You never do that. You always use the same source. I guess (lot of guessing here) you thought you simply skip the texture refresh so it still shows the old image. Unfortunately that works at the first change only. As soon as you call texture.refresh() you get the current (refreshed image).

I suggest you try:


texture.refresh(False) # no refresh of the source, but refresh of the mesh
anotherTexture() # refresh of the source and refresh of the mesh

in exactly this order.

Theoretically the firsts operation should update the first mesh with the image that was loaded at the previous frame. The second operation updates the source and the second mesh. But I have no idea if that really works.

If not I guess you need to work with ImageBuff and copy the content of the ImageRender source to the ImageBuff source.

I hope it helps a bit.

Thanks @Monster!! That is exactly what I was looking for :smiley: