void upload(const void * data, int width, int height, rs::format format) { // If the frame timestamp has changed since the last time show(...) was called, re-upload the texture if(!texture) glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); switch(format) { case rs::format::any: throw std::runtime_error("not a valid format"); case rs::format::z16: case rs::format::disparity16: rgb.resize(width * height * 3); make_depth_histogram(rgb.data(), reinterpret_cast<const uint16_t *>(data), width, height); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb.data()); break; case rs::format::xyz32f: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_FLOAT, data); break; case rs::format::yuyv: // Display YUYV by showing the luminance channel and packing chrominance into ignored alpha channel glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data); break; case rs::format::rgb8: case rs::format::bgr8: // Display both RGB and BGR by interpreting them RGB, to show the flipped byte ordering. Obviously, GL_BGR could be used on OpenGL 1.2+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); break; case rs::format::rgba8: case rs::format::bgra8: // Display both RGBA and BGRA by interpreting them RGBA, to show the flipped byte ordering. Obviously, GL_BGRA could be used on OpenGL 1.2+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); break; case rs::format::y8: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data); break; case rs::format::y16: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_SHORT, data); break; case rs::format::raw10: // Visualize Raw10 by performing a naive downsample. Each 2x2 block contains one red pixel, two green pixels, and one blue pixel, so combine them into a single RGB triple. rgb.clear(); rgb.resize(width/2 * height/2 * 3); auto out = rgb.data(); auto in0 = reinterpret_cast<const uint8_t *>(data), in1 = in0 + width*5/4; for(int y=0; y<height; y+=2) { for(int x=0; x<width; x+=4) { *out++ = in0[0]; *out++ = (in0[1] + in1[0]) / 2; *out++ = in1[1]; // RGRG -> RGB RGB *out++ = in0[2]; *out++ = (in0[3] + in1[2]) / 2; *out++ = in1[3]; // GBGB in0 += 5; in1 += 5; } in0 = in1; in1 += width*5/4; } glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width/2, height/2, 0, GL_RGB, GL_UNSIGNED_BYTE, rgb.data()); break; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glBindTexture(GL_TEXTURE_2D, 0); }
inline void draw_depth_histogram(const uint16_t depth_image[], int width, int height) { static uint8_t rgb_image[640*480*3]; make_depth_histogram(rgb_image, depth_image, width, height); glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb_image); }