Example #1
0
void display(hitable* world, camera& cam)
{
    CALL_GL_API(::glClearColor(0.0f, 0.5f, 1.0f, 1.0f));
    CALL_GL_API(::glClearDepthf(1.0f));
    CALL_GL_API(::glClearStencil(0));
    CALL_GL_API(::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));

    CALL_GL_API(::glUseProgram(g_program));

    GLfloat invScreen[4] = { 1.0f / WIDTH, 1.0f / HEIGHT, 0.0f, 0.0f };
    auto hInvScreen = GetHandle(g_program, "invScreen");
    CALL_GL_API(::glUniform4fv(hInvScreen, 1, invScreen));

    CALL_GL_API(::glActiveTexture(GL_TEXTURE0));

    CALL_GL_API(::glBindTexture(GL_TEXTURE_2D, g_tex));

    auto hImage = GetHandle(g_program, "image");
    CALL_GL_API(glUniform1i(hImage, 0));

    float lum = 0.0f;
    float maxlum = 0.0f;

    timer time;
    time.begin();

#ifdef ENABLE_MULTI_THREAD
    int step = ny / thread_num;
    int begin = 0;

    for (int i = 0; i < thread_num; i++) {
        g_threadData[i].idx = i;
        g_threadData[i].begin = begin;
        begin += step;
        
        g_threadData[i].end = begin + step;
        g_threadData[i].end = (g_threadData[i].end > HEIGHT ? HEIGHT : g_threadData[i].end);

        g_threadData[i].world = world;
        g_threadData[i].cam = &cam;

        g_eventWorker[i].Set();

        g_threads[i].Start([&](void* userData, bool running) {
            ThreadData* data = (ThreadData*)userData;
            onDisplay(data, running);
        }, &g_threadData[i]);
    }

    for (int i = 0; i < thread_num; i++) {
        g_eventMain[i].Wait();
        g_eventMain[i].Reset();
    }

    for (int i = 0; i < thread_num; i++) {
        lum += g_sumY[i];
        maxlum = math::CMath::Max(g_maxLum[i], maxlum);
    }

    lum /= thread_num;
#else
    onDisplay(world, &cam, 0, 0, ny, true);

    lum = g_sumY[0];
    maxlum = g_maxLum[0];
#endif

    auto elapsed = time.end();
    printf("Elapsed[%f]\n", elapsed);

    static uint8_t s_color[HEIGHT][WIDTH][4];
    static float fMiddleGrey = 0.18f;

    static const vec3 RGB2Y(+0.29900f, +0.58700f, +0.11400f);
    static const vec3 RGB2Cb(-0.16874f, -0.33126f, +0.50000f);
    static const vec3 RGB2Cr(+0.50000f, -0.41869f, -0.08131f);
    static const vec3 YCbCr2R(+1.00000f, +0.00000f, +1.40200f);
    static const vec3 YCbCr2G(+1.00000f, -0.34414f, -0.71414f);
    static const vec3 YCbCr2B(+1.00000f, +1.77200f, +0.00000f);

    // NOTE
    // HDR
    // http://t-pot.com/program/123_ToneMapping/index.html

    float coeff = 0.18f / exp(lum);
    float l_max = coeff * maxlum;

    for (int j = 0; j < ny; j++) {
        for (int i = 0; i < nx; i++) {
#if 1
            vec3 col(g_color[j][i][0], g_color[j][i][1], g_color[j][i][2]);

            float y = dot(RGB2Y, col);
            float cb = dot(RGB2Cb, col);
            float cr = dot(RGB2Cr, col);

            y = coeff * y;
            y = y * (1.0f + y / (l_max * l_max)) / (1.0f + y);

            vec3 ycbcr(y, cb, cr);

            float r = dot(YCbCr2R, ycbcr);
            float g = dot(YCbCr2G, ycbcr);
            float b = dot(YCbCr2B, ycbcr);

            int ir = int(255.9f * r);
            int ig = int(255.9f * g);
            int ib = int(255.9f * b);

            s_color[j][i][0] = math::CMath::Clamp(ir, 0, 255);
            s_color[j][i][1] = math::CMath::Clamp(ig, 0, 255);
            s_color[j][i][2] = math::CMath::Clamp(ib, 0, 255);
#else
            auto r = 2 * int(255.9f * g_color[j][i][0] * div[0]);
            auto g = 2 * int(255.9f * g_color[j][i][1] * div[1]);
            auto b = 2 * int(255.9f * g_color[j][i][2] * div[2]);

            s_color[j][i][0] = math::CMath::Clamp(r, 0, 255);
            s_color[j][i][1] = math::CMath::Clamp(g, 0, 255);
            s_color[j][i][2] = math::CMath::Clamp(b, 0, 255);
#endif
        }
    }

    CALL_GL_API(::glTexSubImage2D(
        GL_TEXTURE_2D,
        0,
        0, 0,
        WIDTH, HEIGHT,
        GL_RGBA,
        GL_UNSIGNED_BYTE,
        s_color));

    CALL_GL_API(::glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
rspfRefPtr<rspfImageData> rspfJpegYCbCrToRgbSource::getTile(
   const rspfIrect& tileRect,
   rspf_uint32 resLevel)
{
   if (!theBlankTile.valid())
   {
      allocate(); // first time through.
   }
   
   if(theBlankTile.valid())
   {
      theBlankTile->setOrigin(tileRect.ul());
      theBlankTile->setWidthHeight(tileRect.width(), tileRect.height());
   }
   
   if(theInputConnection)
   {
      rspfRefPtr<rspfImageData> imageData =
         theInputConnection->getTile(tileRect, resLevel);

      if(!imageData.valid())
      {
         return theBlankTile;
      }
      if((isSourceEnabled())&&
         (imageData->getNumberOfBands()==3)&&
         (imageData->getScalarType()==RSPF_UCHAR)&&
         (imageData->getDataObjectStatus()!=RSPF_NULL)&&
         (imageData->getDataObjectStatus()!=RSPF_EMPTY))
      {
         rspf_uint8* bands[3];
         
         bands[0] = static_cast<rspf_uint8*>(imageData->getBuf(0));
         bands[1] = static_cast<rspf_uint8*>(imageData->getBuf(1));
         bands[2] = static_cast<rspf_uint8*>(imageData->getBuf(2));
         
         long height = imageData->getHeight();
         long width  = imageData->getWidth();
         long offset = 0;
         for(long row = 0; row < height; ++row)
         {
            for(long col = 0; col < width; ++col)
            {
               
               rspfJpegYCbCrVector ycbcr(bands[0][offset],
                                          bands[1][offset],
                                          bands[2][offset]);
               rspfRgbVector rgb(ycbcr);
               
               
               bands[0][offset] = rgb.getR();
               bands[1][offset] = rgb.getG();
               bands[2][offset] = rgb.getB();
               
               ++offset;
            }
         }
         imageData->validate();
      }
      return imageData;
   }
   
   return theBlankTile;
}