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; }