1
$\begingroup$

I have begun learning how to create a Ray Tracer and 1 thing I am confused about is how the pixel color from a Ray Tracer is stored into an image. Do we use SetPixel for a Bitmap? Do we use a third party library like libpng?

Most tutorials don't really explain this well online, so if anyone can explain what the most common method for this is that would be great.

$\endgroup$
1
  • 1
    $\begingroup$ OpenEXR is widely used in industry, with everything you'd expect: HDR, 32-bit float and 'half' float channel support, and support for color management, which is critical when you're using profiles to make sure the colors on your monitor match up with rushes you're viewing on, say, a projector. A lot of what it offers might not be useful to you, but the software is free, and there are plenty of minimal examples. $\endgroup$
    – Brett Hale
    Nov 29, 2016 at 13:47

3 Answers 3

3
$\begingroup$

It doesn't matter. All that matters is that you can store information per pixel.

In most cases this means allocating a x*y array of ints (for 3 byte-sized channels of RGB) to store the pixel values and then feed it into your image compression library of choice to save it out to disk.

$\endgroup$
3
$\begingroup$

Depends if you are talking about CPU or GPU ray tracer. For CPU you generally simply allocate an array of width * height float4's (i.e. for RGB & alpha) and for GPU you allocate a texture (e.g. R16G16B16A16F or R32G32B32A32F format). It depends on your case if you really need the alpha though. The target on CPU is then simply accessed by image[(x+y*width)*4] (image=float array), and on GPU image[uint2(x, y)] (image=UAV).

You generally want this target to be a float format (16-bit or 32-bit) to be able to handle high dynamic range (HDR) of luminance in the scene (think of a scene illuminated by Sun = ~100,000 Lux vs Moon = ~1 Lux), that gets then exposed using camera settings, tone mapped and converted to sRGB space to be viewable on regular 8bpc devices.

If you are with a very strict with memory budget, you may allocate LDR target (e.g. R8G8B8A8_UNORM) and perform camera exposure, tone mapping & sRGB conversion before writing the result to the render target. This has bunch of issues though, e.g. you would need the camera exposure value prior to rendering, which can be a challenge for camera auto-exposure, so it's generally adviced to use HDR target instead.

$\endgroup$
1
  • $\begingroup$ I would also mention that LDR is probably more suited to eye-side ray-tracing as you don't need to accumulate a lot of small parts that often. $\endgroup$
    – akaltar
    Nov 11, 2016 at 1:53
1
$\begingroup$

Do you use MFC? If so, here's a code snippet to write a red gradient image using MFC's CImage. The top of the image is redder. Because height is positive, it's a bottom-up DIB and higher values of y (in GetPixelAddress()) point to earlier scanlines (i.e. lower in the image):

    const unsigned int imageWidth = 100;
    const unsigned int imageHeight = 255;
    CImage img;
    img.Create(imageWidth,imageHeight,24,0);
    for(unsigned int x = 0; x < imageWidth; ++x)
    {
        for(unsigned int y = 0; y < imageHeight; ++y)
        {
            // Note BGR, not RGB!
            unsigned char* pixelP = static_cast<unsigned char*>(img.GetPixelAddress(x,imageHeight - 1 - y));
            pixelP[0] = 0;
            pixelP[1] = 0;
            pixelP[2] = y;
        }
    }

    HRESULT hr = img.Save("c:\\red.bmp",Gdiplus::ImageFormatBMP);

There's many image formats, and many different ways to do this. I'll probably migrate away from CImage at some future point...

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.