Manta Interactive Ray Tracer Development Mailing List

Text archives Help


Re: [Manta] r1967 - in trunk: Core/Color Image Model/Textures


Chronological Thread 
  • From: Solomon Boulos <boulos@cs.utah.edu>
  • Cc: MANTA <manta@sci.utah.edu>
  • Subject: Re: [Manta] r1967 - in trunk: Core/Color Image Model/Textures
  • Date: Sun, 6 Jan 2008 13:34:08 -0800

On my system, I have not managed a perfect reproduction of a macbeth color checker (http://www.drycreekphoto.com/images/Charts/MacbethCC-sRGB.jpg ) on a rectangle. This might be due to Apple's fancy color calibration stuff, so perhaps someone can try this out on a Linux system? Unfortunately, it needs to be a non-laptop system so that the display isn't of poor quality.

To enable linearization of textures, simply call LoadColorImageTexture with linearize set to true (or for debugging change the default). To enable gamma correction for display, edit SimpleImage_special.cc and change the MANTA_USE_SRGB define to 1. Note: on my system it's very close, so I think it's possible we just need to use the sRGB framebuffer extension, but it took me a long time to get to here so I'm taking a break.

Solomon

On Jan 6, 2008, at 1:29 PM, boulos@sci.utah.edu wrote:

Author: boulos
Date: Sun Jan  6 14:28:57 2008
New Revision: 1967

Modified:
  trunk/Core/Color/ColorSpace.h
  trunk/Core/Color/GrayTraits.h
  trunk/Core/Color/RGBTraits.h
  trunk/Image/SimpleImage_special.cc
  trunk/Model/Textures/ImageTexture.cc
  trunk/Model/Textures/ImageTexture.h
Log:
Core/Color/ColorSpace.h
Core/Color/GrayTraits.h
Core/Color/RGBTraits.h

Adding a linearize function to ColorSpaces that describes how to
convert a gamma corrected value into a linear value.

The RGBTraits class uses the sRGB conversion (with simplified
approximation ifdef'ed out), while GrayTraits assumes linear (this
might not be a good idea for grey bump maps, but not many formats
store only 1 channel anyway).

Image/SimpleImage_special.cc

Adding an SSE implementation of RGBtoSRGB (the opposite of linearize)
to prepare Manta's linear values for display. After a lot of
searching, I think we have to tell OpenGL that our framebuffer will
be sRGB (otherwise it seems to be up to the vendor).

This is currently disabled by default.

Model/Textures/ImageTexture.cc
Model/Textures/ImageTexture.h

Adding support for linearizing image textures on input. This is also
disabled by default to retain current behavior for people that expect
this during the SIGGRAPH season ;).


Modified: trunk/Core/Color/ColorSpace.h
= = = = = = = = ======================================================================
--- trunk/Core/Color/ColorSpace.h       (original)
+++ trunk/Core/Color/ColorSpace.h       Sun Jan  6 14:28:57 2008
@@ -260,6 +260,10 @@
      return Traits::luminance(data);
    }

+    static ComponentType linearize(ComponentType val) {
+      return Traits::linearize(val);
+    }
+
#ifndef SWIG // Swig gets confused about NumComponents, and you can
             // use the regular [] operators.
    ComponentType data[NumComponents];
@@ -320,7 +324,7 @@
    }
    static bool force_initialize;
  };
-
+
}

#endif

Modified: trunk/Core/Color/GrayTraits.h
= = = = = = = = ======================================================================
--- trunk/Core/Color/GrayTraits.h       (original)
+++ trunk/Core/Color/GrayTraits.h       Sun Jan  6 14:28:57 2008
@@ -36,6 +36,10 @@
    static ComponentType luminance(const ComponentType data) {
      return data;
    }
+
+    static ComponentType linearize(const ComponentType val) {
+      return val;
+    }
  };
}


Modified: trunk/Core/Color/RGBTraits.h
= = = = = = = = ======================================================================
--- trunk/Core/Color/RGBTraits.h        (original)
+++ trunk/Core/Color/RGBTraits.h        Sun Jan  6 14:28:57 2008
@@ -5,6 +5,7 @@
#include <Core/Color/RGBColor.h>
#include <Core/Color/Conversion.h>
#include <Core/Persistent/MantaRTTI.h>
+#include <Core/Math/Expon.h>

namespace Manta {
  class ArchiveElement;
@@ -41,6 +42,19 @@

    static ComponentType luminance(const ComponentType data[3]) {
return data[0] * ComponentType(0.3) + data[1] * ComponentType(0.59) + data[2] * ComponentType(0.11);
+    }
+
+    // Convert from SRGB to RGB
+    static ComponentType linearize(const ComponentType val) {
+#if 1
+      if (val > 0.04045) {
+        return Pow((val + .055)/(1.055), 2.4);
+      } else {
+        return val / 12.92;
+      }
+#else
+      return Pow(val, 2.2f);
+#endif
    }

static void readwrite(ArchiveElement* archive, ComponentType data[3]);

Modified: trunk/Image/SimpleImage_special.cc
= = = = = = = = ======================================================================
--- trunk/Image/SimpleImage_special.cc  (original)
+++ trunk/Image/SimpleImage_special.cc  Sun Jan  6 14:28:57 2008
@@ -1,4 +1,5 @@
-
+#include <Core/Math/ExponSSE.h>
+#include <Core/Math/SSEDefs.h>
#include <Image/SimpleImage.h>
#include <iostream>
#include <MantaSSE.h>
@@ -6,6 +7,26 @@
using namespace Manta;
using namespace std;

+#define MANTA_USE_SRGB 0
+
+#if MANTA_USE_SRGB
+inline __m128 RGBtoSRGB(__m128 val) {
+#if 1
+  // NOTE(boulos): This conversion follows that given in the OpenGL
+  // sRGB texture spec (question 14):
+ // http://opengl.org/registry/specs/EXT/texture_sRGB.txt and that of
+  // the framebuffer spec:
+  // http://www.opengl.org/registry/specs/EXT/framebuffer_sRGB.txt
+  __m128 use_gamma = _mm_cmplt_ps(_mm_set1_ps(.0031308f), val);
+  __m128 linear_ver = _mm_mul_ps(val, _mm_set1_ps(12.92f));
+ __m128 gamma_ver = _mm_sub_ps(_mm_mul_ps(_mm_set1_ps(1.055f), PowSSEMathH(val, _mm_set1_ps(0.41666f), use_gamma)), _mm_set1_ps(. 055f));
+  return mask4(use_gamma, gamma_ver, linear_ver);
+#else
+  return PowSSEMathH(val, _mm_set1_ps(1.f/2.2f));
+#endif
+}
+#endif
+
template<>
void SimpleImage<ARGB8Pixel>::set(const Fragment& fragment)
{
@@ -24,9 +45,15 @@
        __m128 r = _mm_load_ps(&fragment.color[0][i]);
        __m128 g = _mm_load_ps(&fragment.color[1][i]);
        __m128 b = _mm_load_ps(&fragment.color[2][i]);
+#if MANTA_USE_SRGB
+        r = RGBtoSRGB(r);
+        g = RGBtoSRGB(g);
+        b = RGBtoSRGB(b);
+#endif
        r = _mm_mul_ps(r, scale);
        g = _mm_mul_ps(g, scale);
        b = _mm_mul_ps(b, scale);
+
        __m128i alpha = _mm_set1_epi32(255);  // alpha
        __m128i r32 = _mm_cvttps_epi32(r); // 32 bits: r0r1r2r3
        __m128i g32 = _mm_cvttps_epi32(g); // 32 bits: g0g1g2g3
@@ -203,7 +230,6 @@
        __m128 g = _mm_load_ps(&fragment.color[1][i]);
        __m128 b = _mm_load_ps(&fragment.color[2][i]);
        __m128 a = _mm_set_ps1(1.0f);  // alpha a0a1a2a3
-
        // This will do the following
        // r = r0r1r2r3       r = r0g0b0a0
        // g = g0g1g2g3   =>  g = r1g1b1a1

Modified: trunk/Model/Textures/ImageTexture.cc
= = = = = = = = ======================================================================
--- trunk/Model/Textures/ImageTexture.cc        (original)
+++ trunk/Model/Textures/ImageTexture.cc        Sun Jan  6 14:28:57 2008
@@ -50,9 +50,11 @@
  // This will potentially throw a InputError exception if there was a
  // problem.
ImageTexture<Color>* LoadColorImageTexture( const std::string& file_name,
-                                              std::ostream* stream )
+                                              std::ostream* stream,
+                                              bool linearize)
  {
    if (stream) (*stream) << "Trying to load "<<file_name<<"\n";
+ if (linearize && stream) (*stream) << "Will linearize on input \n";
    Image *image = 0;

    // Load the image.
@@ -101,7 +103,7 @@
    }

    // Create the texture.
-    ImageTexture<Color> *texture = new ImageTexture<Color>( image );
+ ImageTexture<Color> *texture = new ImageTexture<Color>(image, linearize);

    // Free time image.
    delete image;

Modified: trunk/Model/Textures/ImageTexture.h
= = = = = = = = ======================================================================
--- trunk/Model/Textures/ImageTexture.h (original)
+++ trunk/Model/Textures/ImageTexture.h Sun Jan  6 14:28:57 2008
@@ -78,7 +78,8 @@
  // problem.  If stream is non null it will write out chatty stuff to
  // that.
ImageTexture<Color>* LoadColorImageTexture( const std::string& file_name,
- std::ostream* stream = 0 );
+ std::ostream* stream = 0,
+ bool linearize = false);

  // Whatever type ValueType ends up being, it needs to have
  // ValueType::ScalarType defined.  I'm not sure what to do for
@@ -88,7 +89,7 @@
  template< typename ValueType >
  class ImageTexture : public Texture< ValueType > {
  public:
-    ImageTexture(const Image* image);
+    ImageTexture(const Image* image, bool linearize = true);
    virtual ~ImageTexture() {}

    virtual void mapValues(Packet<ValueType>& results,
@@ -210,7 +211,7 @@
  };

  template< class ValueType >
-  ImageTexture< ValueType >::ImageTexture(const Image* image):
+ ImageTexture< ValueType >::ImageTexture(const Image* image, bool linearize) :
    scale(VectorT< ScalarType, 2 >(1,1)),
    interpolation_method(NearestNeighbor),
    u_edge(Wrap), v_edge(Wrap)
@@ -223,15 +224,34 @@
    }
    texture.resize(xres, yres);

-    // Now copy over the data
-    for(int y = 0; y < yres; y++) {
-      for(int x = 0; x < xres; x+=Fragment::MaxSize) {
-        int end = x + Fragment::MaxSize;
-        if (end > xres) end = xres;
-        Fragment fragment(x, end, y, 0);
-        image->get(fragment);
-        for(int i = fragment.begin(); i < fragment.end(); i++) {
-          texture(x+i, y) = fragment.getColor(i);
+    if (linearize) {
+      // Now copy over the data
+      for(int y = 0; y < yres; y++) {
+        for(int x = 0; x < xres; x+=Fragment::MaxSize) {
+          int end = x + Fragment::MaxSize;
+          if (end > xres) end = xres;
+          Fragment fragment(x, end, y, 0);
+          image->get(fragment);
+          for(int i = fragment.begin(); i < fragment.end(); i++) {
+            ValueType new_value = fragment.getColor(i);
+            for (int c = 0; c < ValueType::NumComponents; c++) {
+              new_value[c] = ValueType::linearize(new_value[c]);
+            }
+            texture(x+i, y) = new_value;
+          }
+        }
+      }
+    } else {
+      // Now copy over the data
+      for(int y = 0; y < yres; y++) {
+        for(int x = 0; x < xres; x+=Fragment::MaxSize) {
+          int end = x + Fragment::MaxSize;
+          if (end > xres) end = xres;
+          Fragment fragment(x, end, y, 0);
+          image->get(fragment);
+          for(int i = fragment.begin(); i < fragment.end(); i++) {
+            texture(x+i, y) = fragment.getColor(i);
+          }
        }
      }
    }






Archive powered by MHonArc 2.6.16.

Top of page