Blender V2.61 - r43446

buffers.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include <stdlib.h>
00020 
00021 #include "buffers.h"
00022 #include "device.h"
00023 
00024 #include "util_debug.h"
00025 #include "util_hash.h"
00026 #include "util_image.h"
00027 #include "util_math.h"
00028 #include "util_opengl.h"
00029 #include "util_time.h"
00030 #include "util_types.h"
00031 
00032 CCL_NAMESPACE_BEGIN
00033 
00034 /* Render Buffers */
00035 
00036 RenderBuffers::RenderBuffers(Device *device_)
00037 {
00038     device = device_;
00039 }
00040 
00041 RenderBuffers::~RenderBuffers()
00042 {
00043     device_free();
00044 }
00045 
00046 void RenderBuffers::device_free()
00047 {
00048     if(buffer.device_pointer) {
00049         device->mem_free(buffer);
00050         buffer.clear();
00051     }
00052 
00053     if(rng_state.device_pointer) {
00054         device->mem_free(rng_state);
00055         rng_state.clear();
00056     }
00057 }
00058 
00059 void RenderBuffers::reset(Device *device, BufferParams& params_)
00060 {
00061     params = params_;
00062 
00063     /* free existing buffers */
00064     device_free();
00065     
00066     /* allocate buffer */
00067     buffer.resize(params.width, params.height);
00068     device->mem_alloc(buffer, MEM_READ_WRITE);
00069     device->mem_zero(buffer);
00070 
00071     /* allocate rng state */
00072     rng_state.resize(params.width, params.height);
00073 
00074     uint *init_state = rng_state.resize(params.width, params.height);
00075     int x, y, width = params.width, height = params.height;
00076     
00077     for(x=0; x<width; x++)
00078         for(y=0; y<height; y++)
00079             init_state[x + y*width] = hash_int_2d(x, y);
00080 
00081     device->mem_alloc(rng_state, MEM_READ_WRITE);
00082     device->mem_copy_to(rng_state);
00083 }
00084 
00085 float4 *RenderBuffers::copy_from_device(float exposure, int sample)
00086 {
00087     if(!buffer.device_pointer)
00088         return NULL;
00089 
00090     device->mem_copy_from(buffer, 0, params.width, params.height, sizeof(float4));
00091 
00092     float4 *out = new float4[params.width*params.height];
00093     float4 *in = (float4*)buffer.data_pointer;
00094     float scale = 1.0f/(float)sample;
00095     
00096     for(int i = params.width*params.height - 1; i >= 0; i--) {
00097         float4 rgba = in[i]*scale;
00098 
00099         rgba.x = rgba.x*exposure;
00100         rgba.y = rgba.y*exposure;
00101         rgba.z = rgba.z*exposure;
00102 
00103         /* clamp since alpha might be > 1.0 due to russian roulette */
00104         rgba.w = clamp(rgba.w, 0.0f, 1.0f);
00105 
00106         out[i] = rgba;
00107     }
00108 
00109     return out;
00110 }
00111 
00112 /* Display Buffer */
00113 
00114 DisplayBuffer::DisplayBuffer(Device *device_)
00115 {
00116     device = device_;
00117     draw_width = 0;
00118     draw_height = 0;
00119     transparent = true; /* todo: determine from background */
00120 }
00121 
00122 DisplayBuffer::~DisplayBuffer()
00123 {
00124     device_free();
00125 }
00126 
00127 void DisplayBuffer::device_free()
00128 {
00129     if(rgba.device_pointer) {
00130         device->pixels_free(rgba);
00131         rgba.clear();
00132     }
00133 }
00134 
00135 void DisplayBuffer::reset(Device *device, BufferParams& params_)
00136 {
00137     draw_width = 0;
00138     draw_height = 0;
00139 
00140     params = params_;
00141 
00142     /* free existing buffers */
00143     device_free();
00144 
00145     /* allocate display pixels */
00146     rgba.resize(params.width, params.height);
00147     device->pixels_alloc(rgba);
00148 }
00149 
00150 void DisplayBuffer::draw_set(int width, int height)
00151 {
00152     assert(width <= params.width && height <= params.height);
00153 
00154     draw_width = width;
00155     draw_height = height;
00156 }
00157 
00158 void DisplayBuffer::draw_transparency_grid()
00159 {
00160     GLubyte checker_stipple_sml[32*32/8] = {
00161         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
00162         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
00163         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
00164         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
00165         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
00166         255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \
00167         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
00168         0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \
00169     };
00170 
00171     glColor4ub(50, 50, 50, 255);
00172     glRectf(0, 0, params.width, params.height);
00173     glEnable(GL_POLYGON_STIPPLE);
00174     glColor4ub(55, 55, 55, 255);
00175     glPolygonStipple(checker_stipple_sml);
00176     glRectf(0, 0, params.width, params.height);
00177     glDisable(GL_POLYGON_STIPPLE);
00178 }
00179 
00180 void DisplayBuffer::draw(Device *device)
00181 {
00182     if(draw_width != 0 && draw_height != 0) {
00183         if(transparent)
00184             draw_transparency_grid();
00185 
00186         device->draw_pixels(rgba, 0, draw_width, draw_height, 0, params.width, params.height, transparent);
00187     }
00188 }
00189 
00190 bool DisplayBuffer::draw_ready()
00191 {
00192     return (draw_width != 0 && draw_height != 0);
00193 }
00194 
00195 void DisplayBuffer::write(Device *device, const string& filename)
00196 {
00197     int w = draw_width;
00198     int h = draw_height;
00199 
00200     if(w == 0 || h == 0)
00201         return;
00202 
00203     /* read buffer from device */
00204     device->pixels_copy_from(rgba, 0, w, h);
00205 
00206     /* write image */
00207     ImageOutput *out = ImageOutput::create(filename);
00208     ImageSpec spec(w, h, 4, TypeDesc::UINT8);
00209     int scanlinesize = w*4*sizeof(uchar);
00210 
00211     out->open(filename, spec);
00212 
00213     /* conversion for different top/bottom convention */
00214     out->write_image(TypeDesc::UINT8,
00215         (uchar*)rgba.data_pointer + (h-1)*scanlinesize,
00216         AutoStride,
00217         -scanlinesize,
00218         AutoStride);
00219 
00220     out->close();
00221 
00222     delete out;
00223 }
00224 
00225 CCL_NAMESPACE_END
00226