00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "framebuffer.h"
00024
00025 #include <cmath>
00026 #include <IL/il.h>
00027 #include <IL/ilu.h>
00028 #include <limits>
00029
00030 using namespace sheep;
00031 using namespace std;
00032 using namespace toxic;
00033
00034 Framebuffer::Framebuffer(int width, int height, Format format) :
00035 m_width(width), m_height(height),
00036 m_pixels(width * height),
00037 m_format(format)
00038 {
00039 assert(m_width > 0);
00040 assert(m_height > 0);
00041 assert(m_pixels > 0);
00042
00043 switch(m_format) {
00044 case RGB_FLOAT_32:
00045 m_bits.m_rgb_float_32 = new pixel_rgb_float_32[m_pixels];
00046 assert(m_bits.m_rgb_float_32);
00047 break;
00048 default:
00049 assert(!"Unknown framebuffer format.");
00050 }
00051
00052 m_inv_width = 1.0 / m_width;
00053 m_inv_height = 1.0 / m_height;
00054 m_half_inv_width = 1.0 / (2.0 * m_width);
00055 m_half_inv_height = 1.0 / (2.0 * m_height);
00056 }
00057
00058 Framebuffer::~Framebuffer() {
00059 switch(m_format) {
00060 case RGB_FLOAT_32:
00061 delete [] m_bits.m_rgb_float_32;
00062 break;
00063 default:
00064 assert(!"Unknown framebuffer format.");
00065 }
00066 }
00067
00068 int Framebuffer::GetSizeInMemory() const {
00069 switch(m_format) {
00070 case RGB_FLOAT_32:
00071 return
00072 sizeof(Framebuffer) +
00073 sizeof(pixel_rgb_float_32) * m_pixels;
00074 break;
00075 default:
00076 assert(!"Unknown framebuffer format.");
00077 }
00078
00079 return 0;
00080 }
00081
00082 void Framebuffer::Clear(Color3 color ) {
00083 switch(m_format) {
00084 case RGB_FLOAT_32:
00085 {
00086 pixel_rgb_float_32 *p = m_bits.m_rgb_float_32;
00087 for(int i = 0; i < m_pixels; ++i, ++p) {
00088 p->m_r = static_cast<float32>(color.m_r);
00089 p->m_g = static_cast<float32>(color.m_g);
00090 p->m_b = static_cast<float32>(color.m_b);
00091 }
00092 }
00093 break;
00094 default:
00095 assert(!"Unknown framebuffer format.");
00096 }
00097 }
00098
00099 void Framebuffer::PlotLine(int x1, int y1, int x2, int y2, const Color3 &color) {
00100 const int dx = x2 - x1;
00101 const int ax = 2 * (dx < 0 ? -dx : dx);
00102 const int sx = dx < 0 ? -1 : 1;
00103
00104 const int dy = y2 - y1;
00105 const int ay = 2 * (dy < 0 ? -dy : dy);
00106 const int sy = dy < 0 ? -1 : 1;
00107
00108 if(ax > ay) {
00109 int d = ay - ax / 2;
00110
00111 while(true) {
00112 SetPixel(x1, y1, color);
00113
00114 if(x1 == x2)
00115 return;
00116
00117 if(d >= 0) {
00118 y1 += sy;
00119 d -= ax;
00120 }
00121
00122 x1 += sx;
00123 d += ay;
00124 }
00125 } else {
00126 int d = ax - ay / 2;
00127
00128 while(true) {
00129 SetPixel(x1, y1, color);
00130
00131 if(y1 == y2)
00132 return;
00133
00134 if(d >= 0) {
00135 x1 += sx;
00136 d -= ay;
00137 }
00138
00139 y1 += sy;
00140 d += ax;
00141 }
00142 }
00143 }
00144
00145 void Framebuffer::Normalize() {
00146 switch(m_format) {
00147 case RGB_FLOAT_32:
00148 {
00149 Real smallest = numeric_limits<Real>::max();
00150 Real largest = -numeric_limits<Real>::max();
00151
00152 pixel_rgb_float_32 *p = m_bits.m_rgb_float_32;
00153
00154 for(int i = 0; i < m_pixels; ++i, ++p) {
00155 if(p->m_r > largest) largest = p->m_r;
00156 if(p->m_g > largest) largest = p->m_g;
00157 if(p->m_b > largest) largest = p->m_b;
00158
00159 if(p->m_r < smallest) smallest = p->m_r;
00160 if(p->m_g < smallest) smallest = p->m_g;
00161 if(p->m_b < smallest) smallest = p->m_b;
00162 }
00163
00164 const Real delta = largest - smallest;
00165
00166 assert(delta >= 0.0);
00167
00168 if(delta > 0.0) {
00169 const Real scale = 1.0 / delta;
00170
00171 p = m_bits.m_rgb_float_32;
00172
00173 for(int i = 0; i < m_pixels; ++i, ++p) {
00174 p->m_r = (p->m_r - smallest) * scale;
00175 p->m_g = (p->m_g - smallest) * scale;
00176 p->m_b = (p->m_b - smallest) * scale;
00177
00178 if(p->m_r < 0.0) p->m_r = 0.0;
00179 if(p->m_g < 0.0) p->m_g = 0.0;
00180 if(p->m_b < 0.0) p->m_b = 0.0;
00181
00182 if(p->m_r > 1.0) p->m_r = 1.0;
00183 if(p->m_g > 1.0) p->m_g = 1.0;
00184 if(p->m_b > 1.0) p->m_b = 1.0;
00185 }
00186 } else {
00187 p = m_bits.m_rgb_float_32;
00188
00189 for(int i = 0; i < m_pixels; ++i, ++p) {
00190 p->m_r = p->m_g = p->m_b = 0.5;
00191 }
00192 }
00193 }
00194 break;
00195 default:
00196 assert(!"Unknown framebuffer format.");
00197 }
00198 }
00199
00200 void Framebuffer::CorrectGamma(Real target_gamma) {
00201 assert(target_gamma > 0.0);
00202
00203 switch(m_format) {
00204 case RGB_FLOAT_32:
00205 {
00206 const float32 inv_target_gamma = static_cast<float32>(1.0 / target_gamma);
00207 pixel_rgb_float_32 *p = m_bits.m_rgb_float_32;
00208 for(int i = 0; i < m_pixels; ++i, ++p) {
00209 p->m_r = powf(p->m_r, inv_target_gamma);
00210 p->m_g = powf(p->m_g, inv_target_gamma);
00211 p->m_b = powf(p->m_b, inv_target_gamma);
00212 }
00213 }
00214 break;
00215 default:
00216 assert(!"Unknown framebuffer format.");
00217 }
00218 }
00219
00220 namespace {
00221 inline
00222 uint8 convert_float32_to_uint8(float32 x) {
00223 assert(x >= 0.0f);
00224
00225 int n = static_cast<int>(x * 256.0f);
00226
00227 if(n > 255)
00228 return 255;
00229 else return static_cast<uint8>(n);
00230 }
00231 }
00232
00233 bool Framebuffer::WriteToDisk(const std::string &filename) const {
00234 uint8 *buffer;
00235
00236 switch(m_format) {
00237 case RGB_FLOAT_32:
00238 {
00239 uint8 *buf = buffer = new uint8[3 * m_pixels];
00240 const pixel_rgb_float_32 *p = m_bits.m_rgb_float_32 + m_pixels - m_width;
00241
00242
00243
00244
00245 for(int y = 0; y < m_height; ++y) {
00246 for(int x = 0; x < m_width; ++x, ++p) {
00247 *buf++ = convert_float32_to_uint8(p->m_r);
00248 *buf++ = convert_float32_to_uint8(p->m_g);
00249 *buf++ = convert_float32_to_uint8(p->m_b);
00250 }
00251 p -= 2 * m_width;
00252 }
00253 }
00254 break;
00255 default:
00256 assert(!"Unknown framebuffer format.");
00257 }
00258
00259 ILuint image_id;
00260 ilGenImages(1, &image_id);
00261 ilBindImage(image_id);
00262
00263 switch(m_format) {
00264 case RGB_FLOAT_32:
00265 ilTexImage(m_width, m_height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, buffer);
00266 break;
00267 default:
00268 assert(!"Unknown framebuffer format.");
00269 }
00270
00271 delete [] buffer;
00272
00273 ilEnable(IL_FILE_OVERWRITE);
00274 ilSaveImage(const_cast<ILstring>(filename.c_str()));
00275
00276 ilDeleteImages(1, &image_id);
00277
00278 return ilGetError() == IL_NO_ERROR;
00279 }