Visual Servoing Platform  version 3.6.1 under development (2025-01-30)
vpPanda3DPostProcessFilter.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  */
30 
31 #include <visp3/ar/vpPanda3DPostProcessFilter.h>
32 
33 #if defined(VISP_HAVE_PANDA3D)
34 
35 #include <lightRampAttrib.h>
36 
37 BEGIN_VISP_NAMESPACE
39 "#version 330\n"
40 "in vec4 p3d_Vertex;\n"
41 "uniform mat4 p3d_ModelViewProjectionMatrix;\n"
42 "in vec2 p3d_MultiTexCoord0;\n"
43 "out vec2 texcoords;\n"
44 
45 "void main()\n"
46 "{\n"
47 " gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;\n"
48 " texcoords = p3d_MultiTexCoord0;\n"
49 "}\n";
50 
52 {
53  CardMaker cm("cm");
54  cm.set_frame_fullscreen_quad();
55  m_renderRoot = NodePath(cm.generate()); // Render root is a 2D rectangle
56  m_renderRoot.set_depth_test(false);
57  m_renderRoot.set_depth_write(false);
58  GraphicsOutput *buffer = m_inputRenderer->getMainOutputBuffer();
59  if (buffer == nullptr) {
61  "Cannot add a postprocess filter to a renderer that does not define getMainOutputBuffer()");
62  }
63  m_shader = Shader::make(Shader::ShaderLanguage::SL_GLSL,
66  m_renderRoot.set_shader(m_shader);
67  m_renderRoot.set_shader_input("dp", LVector2f(1.0 / buffer->get_texture()->get_x_size(), 1.0 / buffer->get_texture()->get_y_size()));
68  m_renderRoot.set_texture(buffer->get_texture());
69  m_renderRoot.set_attrib(LightRampAttrib::make_identity());
70 }
71 
73 {
74  m_cameraPath = m_window->make_camera();
75  m_camera = (Camera *)m_cameraPath.node();
76  PT(OrthographicLens) lens = new OrthographicLens();
77  lens->set_film_size(2, 2);
78  lens->set_film_offset(0, 0);
79  lens->set_near_far(-1000, 1000);
80  m_camera->set_lens(lens);
81  m_cameraPath = m_renderRoot.attach_new_node(m_camera);
82  m_camera->set_scene(m_renderRoot);
83 }
84 
86 {
87 
88  if (m_window == nullptr) {
89  throw vpException(vpException::fatalError, "Cannot setup render target when window is null");
90  }
91  FrameBufferProperties fbp = getBufferProperties();
92  WindowProperties win_prop;
94 
95  // Don't open a window - force it to be an offscreen buffer.
96  int flags = GraphicsPipe::BF_refuse_window | GraphicsPipe::BF_resizeable;
97  GraphicsOutput *windowOutput = m_window->get_graphics_output();
98  GraphicsEngine *engine = windowOutput->get_engine();
99  GraphicsStateGuardian *gsg = windowOutput->get_gsg();
100  GraphicsPipe *pipe = windowOutput->get_pipe();
101  m_buffer = engine->make_output(pipe, m_name, m_renderOrder,
102  fbp, win_prop, flags,
103  gsg, windowOutput);
104  if (m_buffer == nullptr) {
105  throw vpException(vpException::fatalError, "Could not create buffer");
106  }
107  m_buffers.push_back(m_buffer);
108  //m_buffer->set_inverted(true);
109  m_texture = new Texture();
110  fbp.setup_color_texture(m_texture);
111  m_buffer->add_render_texture(m_texture, m_isOutput ? GraphicsOutput::RenderTextureMode::RTM_bind_or_copy : GraphicsOutput::RenderTextureMode::RTM_copy_texture);
112  m_buffer->set_clear_color(LColor(0.f));
113  m_buffer->set_clear_color_active(true);
114  DisplayRegion *region = m_buffer->make_display_region();
115  if (region == nullptr) {
116  throw vpException(vpException::fatalError, "Could not create display region");
117  }
118  region->set_camera(m_cameraPath);
119  region->set_clear_color(LColor(0.f));
120 }
121 
123 {
124  unsigned int previousH = m_renderParameters.getImageHeight(), previousW = m_renderParameters.getImageWidth();
125  bool resize = previousH != params.getImageHeight() || previousW != params.getImageWidth();
126 
127  m_renderParameters = params;
128  if (m_window != nullptr) {
129  GraphicsOutput *buffer = m_inputRenderer->getMainOutputBuffer();
130  m_renderRoot.set_shader_input("dp", LVector2f(1.0 / buffer->get_texture()->get_x_size(), 1.0 / buffer->get_texture()->get_y_size()));
131  }
132  if (resize) {
133  for (GraphicsOutput *buffer: m_buffers) {
134  //buffer->get_type().is_derived_from()
135  GraphicsBuffer *buf = dynamic_cast<GraphicsBuffer *>(buffer);
136  if (buf == nullptr) {
137  throw vpException(vpException::fatalError, "Panda3D: could not cast to GraphicsBuffer when rendering.");
138  }
139  else {
141  }
142  }
143  }
144 }
145 
147 {
148  if (!m_isOutput) {
149  throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
150  }
151 
153  const unsigned numComponents = m_texture->get_num_components();
154  int rowIncrement = I.getWidth() * numComponents; // we ask for only 8 bits image, but we may get an rgb image
155  unsigned char *data = (unsigned char *)(&(m_texture->get_ram_image().front()));
156  // Panda3D stores data upside down
157  data += rowIncrement * (I.getHeight() - 1);
158  rowIncrement = -rowIncrement;
159 
160  for (unsigned int i = 0; i < I.getHeight(); ++i) {
161  unsigned char *colorRow = I[i];
162  for (unsigned int j = 0; j < I.getWidth(); ++j) {
163  colorRow[j] = data[j * numComponents];
164  }
165  data += rowIncrement;
166  }
167 }
168 
170 {
171  if (!m_isOutput) {
172  throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
173  }
174 
176  const unsigned numComponents = m_texture->get_num_components();
177  int rowIncrement = I.getWidth() * numComponents; // we ask for only 8 bits image, but we may get an rgb image
178  float *data = (float *)(&(m_texture->get_ram_image().front()));
179  // Panda3D stores data upside down
180  data += rowIncrement * (I.getHeight() - 1);
181  rowIncrement = -rowIncrement;
182 
183  for (unsigned int i = 0; i < I.getHeight(); ++i) {
184  vpRGBf *colorRow = I[i];
185  for (unsigned int j = 0; j < I.getWidth(); ++j) {
186  colorRow[j].B = data[j * numComponents];
187  colorRow[j].G = data[j * numComponents + 1];
188  colorRow[j].R = data[j * numComponents + 2];
189  }
190  data += rowIncrement;
191  }
192 }
193 
194 END_VISP_NAMESPACE
195 
196 #elif !defined(VISP_BUILD_SHARED_LIBS)
197 // Work around to avoid warning: libvisp_ar.a(vpPanda3DPostProcessFilter.cpp.o) has no symbols
198 void dummy_vpPanda3DPostProcessFilter() { };
199 
200 #endif
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ fatalError
Fatal error.
Definition: vpException.h:72
unsigned int getWidth() const
Definition: vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:544
unsigned int getHeight() const
Definition: vpImage.h:181
NodePath m_renderRoot
Rendering parameters.
PointerTo< Camera > m_camera
Node containing all the objects and the camera for this renderer.
PointerTo< WindowFramework > m_window
Rendering priority for this renderer and its buffers. A lower value will be rendered first....
int m_renderOrder
name of the renderer
std::vector< GraphicsOutput * > m_buffers
NodePath of the camera.
vpPanda3DRenderParameters m_renderParameters
Pointer to owning window, which can create buffers etc. It is not necessarily visible.
std::string m_fragmentShader
Whether this filter is an output to be used and should be copied to ram.
virtual FrameBufferProperties getBufferProperties() const =0
static const std::string FILTER_VERTEX_SHADER
void getRenderBasic(vpImage< unsigned char > &I) const
std::shared_ptr< vpPanda3DBaseRenderer > m_inputRenderer
PointerTo< GraphicsOutput > m_buffer
virtual void setupScene() VP_OVERRIDE
Initialize the scene for this specific renderer.
void setRenderParameters(const vpPanda3DRenderParameters &params) VP_OVERRIDE
Set new rendering parameters. If the scene has already been initialized, the renderer camera is updat...
void setupRenderTarget() VP_OVERRIDE
Initialize buffers and other objects that are required to save the render.
void setupCamera() VP_OVERRIDE
Initialize camera. Should be called when the scene root of this render has already been created.
Rendering parameters for a panda3D simulation.
Definition: vpRGBf.h:64
float B
Blue component.
Definition: vpRGBf.h:157
float G
Green component.
Definition: vpRGBf.h:156
float R
Red component.
Definition: vpRGBf.h:155