Blender V2.61 - r43446
|
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