Simple background image that change every fram

I want to display image on the background of the scene (no skycube or skydome; just 800x600 image on the background, always facing camera).
I want to change this image every frame (with data form a webcam but also data from fractal generated in the memory. (so OpenCVexture wan’t go)
What is the most efficient and eassyest :wink: way to do that?
Currently I’m putting image in the background like this:

((DisplayRegion*) window->get_camera(0)->    get_display_region(0))->set_sort(20);
window->get_display_region_3d()-> set_clear_color_active(false);
window->get_display_region_2d()-> set_clear_color_active(true);

    CardMaker cm("bcg");
    PointerTo<PandaNode> pn = cm.generate();
    NodePath n = window->get_render_2d().attach_new_node(pn);
    Texture *t = TexturePool::load_texture("bcg.png");
    n.set_bin("background", 0);

But don’t know how to change texture data. I was considering texture->set_void_ptr or set_raw_data
but it ins’t obvious how to convert my row data RGBRGBRGB… to fit classes.

I was looking for solution like

texture->set_new_pixel_buffer_ptr(void* mem, newWidth, newHeight, newBpp)

and then


But any other solution wold be ok. :wink:

You can call modify_ram_image, which returns a PTA(uchar) (Panda’s reference-counted equivalent of uchar*) that you can modify.

Here’s an example:

#include "pandaFramework.h"
#include "cardMaker.h"
#include "texture.h"
#include "asyncTaskManager.h"
#include "asyncTask.h"
#include "perlinNoise3.h"
#include "math.h"

static const int tsize = 64;
static const double scale = 16.0;
static const double period = 20.0;
static const double speed = 1.0;

PandaFramework framework;

class FlowTask : public AsyncTask {
  FlowTask(Texture *tex);
  virtual DoneStatus do_task();
  inline unsigned char pixel(double n) {
    return (unsigned char)(n * 127.0 + 128.0);

  PerlinNoise3 _red, _grn, _blu;
  PT(Texture) _tex;

FlowTask::FlowTask(Texture *tex) : 
  _red(tsize, tsize, period),
  _grn(tsize, tsize, period),
  _blu(tsize, tsize, period),
  _red.set_scale(scale, scale, speed);
  _grn.set_scale(scale, scale, speed);
  _blu.set_scale(scale, scale, speed);

FlowTask::DoneStatus FlowTask::
do_task() {
  PTA_uchar image = _tex->modify_ram_image();
  double t = get_elapsed_time() / period;
  t = (t - floor(t)) * period;

  for (int yi = 0; yi < tsize; ++yi) {
    for (int xi = 0; xi < tsize; ++xi) {
      int i = (yi * tsize + xi) * 3;
      image[i] = pixel(_blu(xi, yi, t));
      image[i + 1] = pixel(_grn(xi, yi, t));
      image[i + 2] = pixel(_red(xi, yi, t));

  return DS_cont;

main(int argc, char *argv[]) {
  framework.open_framework(argc, argv);

  WindowFramework *window = framework.open_window();

  CardMaker cm("cm");
  cm.set_frame(-0.9, 0.9, -0.9, 0.9);
  NodePath card = window->get_render_2d().attach_new_node(cm.generate());
  PT(Texture) tex = new Texture("tex");
  tex->setup_2d_texture(tsize, tsize, Texture::T_unsigned_byte, Texture::F_rgb);
  AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
  task_mgr->add(new FlowTask(tex));


  return (0);

Thanks, that works.

Actually, after reading rdb replay, i come back to put my code as example, but I see that example is already here!

So, I only add that I had problems before i realized that result of modify_ram_image can’t be cashed as char* pointer :wink:

I tried the code (using Panda 1.6.2) described above and managed to get input from the webcam and render it into a card through a texture.

However I haven’t been able to send the card to the background using the get_render_2d method. Any help would be appreciated! Thanks!

I’m actually sending to background to the card reparenting it to the camera and setting the bin and depth attributes …

    webcamcard = NodePath(cm.generate()); 
    webcamcard.reparent_to (window->get_camera_group()); 
    webcamcard.set_pos (window->get_render(),0.0,4.0,0.0);

    webcamcard.set_bin("background", 0); 
    webcamcard.set_depth_write (false); 

but I rather parent the card to the render2d

By default, render2d renders after render, so that gui items are drawn on top of the 3-D scene. You can change this so that render2d is drawn first, but then all of render2d will be behind the 3-D scene. If that’s OK to you, you can do it with this:


Note that render and render2d each have their own DisplayRegion, and that the DisplayRegions are drawn in order according to their sort values. So setting render2d’s sort value to a negative number makes it draw before render (whose sort value is 0).

If you want to use a render2d-like scene graph for your background card, and still have gui elements on top, then you will need to create a third DisplayRegion for this purpose. This is easy to do; examine the code in windowFramework.cxx for examples, or look in this forum, or look in the manual.


Well it seems in Panda 1.6 there is no get_display_region* in class WindowFramework, nor a get_graphics_output so I can create a new display region …

Use get_graphics_window(). You can also get to the DisplayRegion from the Camera node.