Visual Servoing Platform  version 3.6.1 under development (2024-10-18)
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
40 in vec4 p3d_Vertex;
41 uniform mat4 p3d_ModelViewProjectionMatrix;
42 in vec2 p3d_MultiTexCoord0;
43 out vec2 texcoords;
44 
45 void main()
46 {
47  gl_Position = p3d_ModelViewProjectionMatrix * p3d_Vertex;
48  texcoords = p3d_MultiTexCoord0;
49 }
50 )shader";
51 
53 {
54  CardMaker cm("cm");
55  cm.set_frame_fullscreen_quad();
56  m_renderRoot = NodePath(cm.generate()); // Render root is a 2D rectangle
57  m_renderRoot.set_depth_test(false);
58  m_renderRoot.set_depth_write(false);
59  GraphicsOutput *buffer = m_inputRenderer->getMainOutputBuffer();
60  if (buffer == nullptr) {
62  "Cannot add a postprocess filter to a renderer that does not define getMainOutputBuffer()");
63  }
64  m_shader = Shader::make(Shader::ShaderLanguage::SL_GLSL,
67  m_renderRoot.set_shader(m_shader);
68  m_renderRoot.set_shader_input("dp", LVector2f(1.0 / buffer->get_texture()->get_x_size(), 1.0 / buffer->get_texture()->get_y_size()));
69  m_renderRoot.set_texture(buffer->get_texture());
70  m_renderRoot.set_attrib(LightRampAttrib::make_identity());
71 }
72 
74 {
75  m_cameraPath = m_window->make_camera();
76  m_camera = (Camera *)m_cameraPath.node();
77  PT(OrthographicLens) lens = new OrthographicLens();
78  lens->set_film_size(2, 2);
79  lens->set_film_offset(0, 0);
80  lens->set_near_far(-1000, 1000);
81  m_camera->set_lens(lens);
82  m_cameraPath = m_renderRoot.attach_new_node(m_camera);
83  m_camera->set_scene(m_renderRoot);
84 }
85 
87 {
88 
89  if (m_window == nullptr) {
90  throw vpException(vpException::fatalError, "Cannot setup render target when window is null");
91  }
92  FrameBufferProperties fbp = getBufferProperties();
93  WindowProperties win_prop;
95 
96  // Don't open a window - force it to be an offscreen buffer.
97  int flags = GraphicsPipe::BF_refuse_window | GraphicsPipe::BF_resizeable;
98  GraphicsOutput *windowOutput = m_window->get_graphics_output();
99  GraphicsEngine *engine = windowOutput->get_engine();
100  GraphicsStateGuardian *gsg = windowOutput->get_gsg();
101  GraphicsPipe *pipe = windowOutput->get_pipe();
102  m_buffer = engine->make_output(pipe, m_name, m_renderOrder,
103  fbp, win_prop, flags,
104  gsg, windowOutput);
105  if (m_buffer == nullptr) {
106  throw vpException(vpException::fatalError, "Could not create buffer");
107  }
108  m_buffers.push_back(m_buffer);
109  //m_buffer->set_inverted(true);
110  m_texture = new Texture();
111  fbp.setup_color_texture(m_texture);
112  m_buffer->add_render_texture(m_texture, m_isOutput ? GraphicsOutput::RenderTextureMode::RTM_bind_or_copy : GraphicsOutput::RenderTextureMode::RTM_copy_texture);
113  m_buffer->set_clear_color(LColor(0.f));
114  m_buffer->set_clear_color_active(true);
115  DisplayRegion *region = m_buffer->make_display_region();
116  if (region == nullptr) {
117  throw vpException(vpException::fatalError, "Could not create display region");
118  }
119  region->set_camera(m_cameraPath);
120  region->set_clear_color(LColor(0.f));
121 }
122 
124 {
125  unsigned int previousH = m_renderParameters.getImageHeight(), previousW = m_renderParameters.getImageWidth();
126  bool resize = previousH != params.getImageHeight() || previousW != params.getImageWidth();
127 
128  m_renderParameters = params;
129  if (m_window != nullptr) {
130  GraphicsOutput *buffer = m_inputRenderer->getMainOutputBuffer();
131  m_renderRoot.set_shader_input("dp", LVector2f(1.0 / buffer->get_texture()->get_x_size(), 1.0 / buffer->get_texture()->get_y_size()));
132  }
133  if (resize) {
134  for (GraphicsOutput *buffer: m_buffers) {
135  //buffer->get_type().is_derived_from()
136  GraphicsBuffer *buf = dynamic_cast<GraphicsBuffer *>(buffer);
137  if (buf == nullptr) {
138  throw vpException(vpException::fatalError, "Panda3D: could not cast to GraphicsBuffer when rendering.");
139  }
140  else {
142  }
143  }
144  }
145 }
146 
148 {
149  if (!m_isOutput) {
150  throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
151  }
152 
154  const unsigned numComponents = m_texture->get_num_components();
155  int rowIncrement = I.getWidth() * numComponents; // we ask for only 8 bits image, but we may get an rgb image
156  unsigned char *data = (unsigned char *)(&(m_texture->get_ram_image().front()));
157  // Panda3D stores data upside down
158  data += rowIncrement * (I.getHeight() - 1);
159  rowIncrement = -rowIncrement;
160 
161  for (unsigned int i = 0; i < I.getHeight(); ++i) {
162  unsigned char *colorRow = I[i];
163  for (unsigned int j = 0; j < I.getWidth(); ++j) {
164  colorRow[j] = data[j * numComponents];
165  }
166  data += rowIncrement;
167  }
168 }
169 
171 {
172  if (!m_isOutput) {
173  throw vpException(vpException::fatalError, "Tried to fetch output of a postprocessing filter that was configured as an intermediate output");
174  }
175 
177  const unsigned numComponents = m_texture->get_num_components();
178  int rowIncrement = I.getWidth() * numComponents; // we ask for only 8 bits image, but we may get an rgb image
179  float *data = (float *)(&(m_texture->get_ram_image().front()));
180  // Panda3D stores data upside down
181  data += rowIncrement * (I.getHeight() - 1);
182  rowIncrement = -rowIncrement;
183 
184  for (unsigned int i = 0; i < I.getHeight(); ++i) {
185  vpRGBf *colorRow = I[i];
186  for (unsigned int j = 0; j < I.getWidth(); ++j) {
187  colorRow[j].B = data[j * numComponents];
188  colorRow[j].G = data[j * numComponents + 1];
189  colorRow[j].R = data[j * numComponents + 2];
190  }
191  data += rowIncrement;
192  }
193 }
194 
195 END_VISP_NAMESPACE
196 
197 #elif !defined(VISP_BUILD_SHARED_LIBS)
198 // Work around to avoid warning: libvisp_ar.a(vpPanda3DPostProcessFilter.cpp.o) has no symbols
199 void dummy_vpPanda3DPostProcessFilter() { };
200 
201 #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:542
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.
std::string m_name
Inverse of VISP_T_PANDA.
PointerTo< WindowFramework > m_window
Pointer to the active panda framework.
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
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:60
float B
Blue component.
Definition: vpRGBf.h:142
float G
Green component.
Definition: vpRGBf.h:141
float R
Red component.
Definition: vpRGBf.h:140