PDA

View Full Version : How to read pixels from a rendered texture?


stefs
09-24-2012, 07:41 AM
I want to read the RGB values from specific texels in a textured polygon, where the texture is a rendered texture attached to a render node. For “normal” textures this works fine by reading from the data array obtained with the texture’s getImageData method.
However, for a texture created with viz.addRenderTexture and attached to the render node using attachTexture, there is no reference to any data returned.

I then tried to attach a texture created with viz.addBlankTexture to the render node. To my surprise this will render correctly to the texture which becomes visible on the rendered polygon. Also a valid reference to a data array is returned with getImageData. But this buffer is empty.

Any suggestions how to access the pixel buffer of a rendered texture?

farshizzo
09-24-2012, 10:00 AM
There is no built-in support for this in Vizard 3. It is possible in Vizard 4 though. In case you decide to upgrade, here is how to get access to the raw image data of a render texture in Vizard 4:imgData = texture.saveToBuffer('<raw>')

stefs
09-28-2012, 02:47 AM
Ok, this seems to work for RGBA textures in Vizard 4.0
But there are other issues now. I try to read the depth values also. First issue is that .getPixelSize() returns zero (also for RGBA textures). By trial and error I found that if the texture is viz.TEX_DEPTH, at least one byte /character is returned per depth value. All other depth formats TEX_DEPTH_16, TEX_DEPTH_24, TEX_DEPTH_32 will cause an "error pixelFormat = 81a5". Please try the script below.
Any ideas how I can get at least 16 bit depth values are greatly appreciated.
(I could work around it by having a specific render pass with a shader that renders Z as RGBA into the color buffer:()

import viz

global render_texture_RGBA
global render_texture_Depth

def set_render_node_view(render_node):
render_node.setBuffer(viz.RENDER_FBO)
render_node.setInheritView(False)
render_node.setMatrix(viz.Transform())
render_node.setPosition(-3.0,0.0,0)
render_node.setEuler([90,0,0])
render_node.setProjectionMatrix(viz.MainWindow.get ProjectionMatrix())

def setup_render_node_RGBA():
global render_texture_RGBA
render_texture_RGBA = viz.addRenderTexture([512, 512], type = viz.TEX_2D, format = viz.TEX_RGBA)
render_node_RGBA = viz.addRenderNode()
render_node_RGBA.setRenderTexture(render_texture_R GBA, buffer = viz.RENDER_COLOR)
render_node_RGBA.setBuffer(viz.RENDER_FBO)
set_render_node_view(render_node_RGBA)

def setup_render_node_Depth(depth_format):
global render_texture_Depth
render_texture_Depth = viz.addRenderTexture([512, 512], type = viz.TEX_2D, format = depth_format)
render_node_Depth = viz.addRenderNode()
render_node_Depth.setRenderTexture(render_texture_ Depth, buffer = viz.AUTO_COMPUTE)
render_node_Depth.setBuffer(viz.RENDER_FBO)
set_render_node_view(render_node_Depth)

def pick_texel_RGBA(texture, pos = [0.5, 0.5]):
size = texture.getSize()
bpt = texture.getPixelSize() # getPixelSize always returns 0
bpt = 4 # set to 4 as we know format is RGBA
data = texture.saveToBuffer('<raw>')
if (data == None):
return None
else:
ix = int(float(size[0]) * pos[0])
iy = int(float(size[1]) * pos[1])
idx = (iy * size[1] + ix ) * bpt
sample = []
for i in range(bpt):
sample.append(ord(data[idx+i]))
return sample

def pick_texel_Depth(texture, pos = [0.5, 0.5]):
size = texture.getSize()
bpt = texture.getPixelSize() # getPixelSize always returns 0
bpt = 1 # set to 1 as this sees to work for format Depth
data = texture.saveToBuffer('<raw>')
if (data == None):
return None
else:
ix = int(float(size[0]) * pos[0])
iy = int(float(size[1]) * pos[1])
idx = (iy * size[1] + ix ) * bpt
sample = []
for i in range(bpt):
sample.append(ord(data[idx+i]))
return sample

def onKeyDown(key):
global render_texture_RGBA
if key == 'p':
print 'RGBA/Depth of texel at [0.5, 0.5] is : ',pick_texel_RGBA(render_texture_RGBA,[0.5, 0.5]), pick_texel_Depth(render_texture_Depth,[0.5, 0.5])
print 'RGBA/Depth of texel at [0.55, 0.5] is : ',pick_texel_RGBA(render_texture_RGBA,[0.55,0.5]), pick_texel_Depth(render_texture_Depth,[0.55, 0.5])
print 'RGBA/Depth of texel at [0.6, 0.5] is : ',pick_texel_RGBA(render_texture_RGBA,[0.6,0.5]), pick_texel_Depth(render_texture_Depth,[0.6, 0.5])

viz.add('ball.wrl')
viz.MainView.setPosition(0.0,0.0,-3)

setup_render_node_RGBA()
setup_render_node_Depth(viz.TEX_DEPTH) # only format that works, will give 8-bit limited depth buffer
#setup_render_node_Depth(viz.TEX_DEPTH_16) # will cause an "error pixelFormat = 81a5" error at texture.saveToBuffer()
#setup_render_node_Depth(viz.TEX_DEPTH_24) # will cause an "error pixelFormat = 81a5" error at texture.saveToBuffer()
#setup_render_node_Depth(viz.TEX_DEPTH_32) # will cause an "error pixelFormat = 81a5" error at texture.saveToBuffer()

tex_quad = viz.addTexQuad()
tex_quad.texture(render_texture_RGBA)
#tex_quad.texture(render_texture_Depth) # show depth buffer, instead
tex_quad.setPosition(1.0,0.0,0)
tex_quad.setScale(viz.MainWindow.getAspectRatio(), 1,1)
viz.callback(viz.KEYDOWN_EVENT,onKeyDown)
viz.go()