RenderKit / ospray

An Open, Scalable, Portable, Ray Tracing Based Rendering Engine for High-Fidelity Visualization

Home Page:http://ospray.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rendering Discrepancy: PixelFilter Impact on Object Positioning

Shijou87 opened this issue · comments

Hello,

I've observed that the scivis renderer doesn't accurately position the image; there's a slight pixel shift in both the x and y coordinates. Upon investigation, I've identified an issue with the default pixel filter employed by the renderer, specifically OSP_PIXELFILTER_GAUSS. This leads to image misalignment when transitioning from OSP_PIXELFILTER_POINT. The problem is resolved when using OSP_PIXELFILTER_POINT, ensuring the image displays at the correct location.

In the provided example, I rendered a basic plane using the scivis renderer. The first render in blue utilized OSP_PIXELFILTER_POINT, while the second in red omitted OSP_PIXELFILTER_POINT (employing OSP_PIXELFILTER_GAUSS), showcasing the pixel shift correction.

image

Generally, I expect that the location of the rendered object should remain unaltered by the filtering process. Do you agree ?

Below is a code snippet that you can use to replicate the problem:

void planeRendering(
  unsigned int width, unsigned int height,
  const char* filename,
  float cameraHeight
) {
  OSPGeometry mesh = ospNewGeometry("mesh");
  std::vector<float> vertices = {
    0, 0, 0,
    0, (float) height, 0,
    (float) width, (float) height, 0,
    (float) width, 0, 0
  };
  OSPData verticesData = ospNewSharedData1D(vertices.data(), OSP_VEC3F, vertices.size()/3);
  ospCommit(verticesData);
  ospSetObject(mesh, "vertex.position", verticesData);
  std::vector<unsigned int> vertexIndices = { 0, 1, 2, 3 };
  OSPData vertexIndicesData = ospNewSharedData1D(vertexIndices.data(), OSP_VEC4UI, vertexIndices.size()/4);
  ospCommit(vertexIndicesData);
  ospSetObject(mesh, "index", vertexIndicesData);
  std::vector<float> normals = {
    0, 0, 1,
    0, 0, 1,
    0, 0, 1,
    0, 0, 1,
  };
  std::vector<float> colors = {
    1, 0, 0,
    1, 0, 0,
    1, 0, 0,
    1, 0, 0
  };
  OSPData normalsData = ospNewSharedData1D(normals.data(), OSP_VEC3F, normals.size()/3);
  ospCommit(normalsData);
  OSPData colorData = ospNewSharedData1D(colors.data(), OSP_VEC3F, colors.size()/3);
  ospCommit(colorData);
  ospSetObject(mesh, "vertex.normal", normalsData);
  ospSetObject(mesh, "color", colorData);
  ospCommit(mesh);

  OSPGroup group = ospNewGroup();
  OSPInstance instance = ospNewInstance(group);
  OSPGeometricModel geometricModel = ospNewGeometricModel(mesh);
  ospCommit(geometricModel);

  std::vector<OSPGeometricModel> planes = {geometricModel};
  OSPData instanceData =  ospNewSharedData1D(planes.data(), OSP_GEOMETRIC_MODEL, planes.size());
  ospCommit(instanceData);
  ospSetObject(group, "geometry", instanceData);
  ospCommit(group);
  ospCommit(instance);

  OSPCamera camera = ospNewCamera("orthographic");

  std::array<float, 3> cameraPos = {(float) width/2, (float) height/2, -1};
  std::array<float, 3> camDir = {0, 0, 1};
  std::array<float, 3> camUp = {0, 1, 0};
  ospSetParam(camera, "position", OSP_VEC3F, cameraPos.data());
  ospSetParam(camera, "direction", OSP_VEC3F, camDir.data());
  ospSetParam(camera, "up", OSP_VEC3F, camUp.data());
  ospSetFloat(camera, "aspect", width / height);
  ospSetFloat(camera, "height", cameraHeight);

  ospCommit(camera);

  OSPLight ambient = ospNewLight("ambient");
  ospSetVec3f(ambient, "color",1.f,1.f,1.f);
  ospCommit(ambient);

  OSPWorld world = ospNewWorld();
  OSPData instances = ospNewSharedData1D(&instance, OSP_INSTANCE, 1);
  ospCommit(instances);
  ospSetObject(world, "instance", instances);
  OSPData lights = ospNewSharedData1D(&ambient, OSP_LIGHT, 1);
  ospSetObject(world, "light", lights);
  ospCommit(world);

  OSPRenderer renderer = ospNewRenderer("scivis");
  // comment this line to test OSP_PIXELFILTER_GAUSS
  ospSetInt(renderer,"pixelFilter",OSP_PIXELFILTER_POINT);
  ospCommit(renderer);

  OSPFrameBuffer framebuffer = ospNewFrameBuffer(width,
          height,
          OSP_FB_RGBA32F,
          OSP_FB_COLOR | OSP_FB_ALBEDO | OSP_FB_NORMAL | OSP_FB_ACCUM | OSP_FB_VARIANCE);

  OSPFuture future = ospRenderFrame(framebuffer, renderer, camera, world);
  ospWait(future, OSP_FRAME_FINISHED);
  ospRelease(future);

  const float* rgbaf = reinterpret_cast<const float*>(ospMapFrameBuffer(framebuffer, OSP_FB_COLOR));
  writePPM(filename, {width,height}, rgbaf);
}

Thanks for reporting and for the reproducer!
If you let multiple frames accumulate (or use pixelSamples >1) then the shift will vanish (and with OSP_PIXELFILTER_GAUSS the edges will be slightly blurred). But I agree that the first sample/frame looks odd. We'll look into implementing a better initial behavior.