Closed paulmelis closed 4 years ago
The denoiser requires using a float frame buffer (OSP_FB_RGBA32F
), which ends up triggering an error with any other pixel format. However, because the error isn't caught, undefined behavior is encountered (which results in a segfault).
Hmmm, using a OSP_FB_RGBA32F
framebuffer (updated test below), I still get the same segfault.
``
using namespace ospcommon::math;
// helper function to write the rendered image as PPM file void writePPM(const char fileName, const vec2i &size, const uint32_t pixel) { FILE file = fopen(fileName, "wb"); if (file == nullptr) { fprintf(stderr, "fopen('%s', 'wb') failed: %d", fileName, errno); return; } fprintf(file, "P6\n%i %i\n255\n", size.x, size.y); unsigned char out = (unsigned char )alloca(3 size.x); for (int y = 0; y < size.y; y++) { const unsigned char in = (const unsigned char )&pixel[(size.y - 1 - y) size.x]; for (int x = 0; x < size.x; x++) { out[3 x + 0] = in[4 x + 0]; out[3 x + 1] = in[4 x + 1]; out[3 x + 2] = in[4 x + 2]; } fwrite(out, 3 size.x, sizeof(char), file); } fprintf(file, "\n"); fclose(file); }
int main(int argc, const char **argv) { // image size vec2i imgSize; imgSize.x = 1024; // width imgSize.y = 768; // height
// camera vec3f cam_pos{0.f, 0.f, 0.f}; vec3f cam_up{0.f, 1.f, 0.f}; vec3f cam_view{0.1f, 0.f, 1.f};
// triangle mesh data
std::vector
std::vector
std::vector
ospLoadModule("denoiser");
// initialize OSPRay; OSPRay parses (and removes) its commandline parameters, // e.g. "--osp:debug" OSPError init_error = ospInit(&argc, argv); if (init_error != OSP_NO_ERROR) return init_error;
// use scoped lifetimes of wrappers to release everything before ospShutdown() { // create and setup camera ospray::cpp::Camera camera("perspective"); camera.setParam("aspect", imgSize.x / (float)imgSize.y); camera.setParam("position", cam_pos); camera.setParam("direction", cam_view); camera.setParam("up", cam_up); camera.commit(); // commit each object to indicate modifications are done
// create and setup model and mesh
ospray::cpp::Geometry mesh("mesh");
mesh.setParam("vertex.position", ospray::cpp::Data(vertex));
mesh.setParam("vertex.color", ospray::cpp::Data(color));
mesh.setParam("index", ospray::cpp::Data(index));
mesh.commit();
// put the mesh into a model
ospray::cpp::GeometricModel model(mesh);
model.commit();
// put the model into a group (collection of models)
ospray::cpp::Group group;
group.setParam("geometry", ospray::cpp::Data(model));
group.commit();
// put the group into an instance (give the group a world transform)
ospray::cpp::Instance instance(group);
instance.commit();
// put the instance in the world
ospray::cpp::World world;
world.setParam("instance", ospray::cpp::Data(instance));
// create and setup light for Ambient Occlusion
ospray::cpp::Light light("ambient");
light.commit();
world.setParam("light", ospray::cpp::Data(light));
world.commit();
// create renderer, choose Scientific Visualization renderer
ospray::cpp::Renderer renderer("scivis");
// complete setup of renderer
renderer.setParam("aoSamples", 1);
renderer.setParam("backgroundColor", 1.0f); // white, transparent
renderer.commit();
// denoise
ospray::cpp::ImageOperation denoise("denoiser");
denoise.commit();
// create and setup framebuffer
ospray::cpp::FrameBuffer framebuffer(
imgSize, OSP_FB_RGBA32F,
OSP_FB_COLOR | OSP_FB_ACCUM | OSP_FB_ALBEDO | OSP_FB_NORMAL);
framebuffer.setParam("imageOperation", ospray::cpp::Data(denoise));
framebuffer.commit();
framebuffer.clear();
// render one frame
framebuffer.renderFrame(renderer, camera, world);
uint8_t *colors = new uint8_t[imgSize.x*imgSize.y*4];
float *pixel;
for (int i = 0; i < imgSize.x*imgSize.y; i++)
{
pixel[3*i+0] = uint8_t(colors[4*i+0] * 255.0f);
pixel[3*i+1] = uint8_t(colors[4*i+1] * 255.0f);
pixel[3*i+2] = uint8_t(colors[4*i+2] * 255.0f);
pixel[3*i+3] = 255;
}
uint32_t *fb = (uint32_t *)framebuffer.map(OSP_FB_COLOR);
framebuffer.unmap(fb);
writePPM("denoised.ppm", imgSize, (uint32_t*)colors);
}
ospShutdown();
return 0; }
Oh, looking at the sample, is the image operation called "frame_denoise"?
(Plus, there conversion errors in my test above when saving the image)
Well, it should be named "denoiser", another oversight...
We can easily make an alias for the name denoiser
and denoise
. The current naming convention is forward looking for users to know if it's a pixel/tile/frame operation, as the order of them can have performance consequences (i.e. the whole frame has to finish before a frame operation can proceed).
In other words, we have several other image operation implementations almost ready to go.
My mistake: apparently we no longer prefix image ops with the type they implement. :)
Okay, working now as expected, closing
The code itself seems to be ok, if I replace the denoiser imageop with a tonemapper one it works fine. But running the above gives me a segfault, looks like a null pointer: