forked from bartvdbraak/blender
Cycles code internals: add CPU kernel support for 3D image textures.
This commit is contained in:
parent
07d1fba367
commit
a2e4ebd36a
@ -93,6 +93,11 @@ void BlenderSession::create_session()
|
||||
/* create scene */
|
||||
scene = new Scene(scene_params, session_params.device);
|
||||
|
||||
/* setup callbacks for builtin image support */
|
||||
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6, _7);
|
||||
scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3);
|
||||
scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3);
|
||||
|
||||
/* create session */
|
||||
session = new Session(session_params);
|
||||
session->scene = scene;
|
||||
@ -121,11 +126,6 @@ void BlenderSession::create_session()
|
||||
session->reset(buffer_params, session_params.samples);
|
||||
|
||||
b_engine.use_highlight_tiles(session_params.progressive_refine == false);
|
||||
|
||||
/* setup callbacks for builtin image support */
|
||||
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3, _4, _5, _6);
|
||||
scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3);
|
||||
scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3);
|
||||
}
|
||||
|
||||
void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_)
|
||||
@ -724,7 +724,7 @@ int BlenderSession::builtin_image_frame(const string &builtin_name)
|
||||
return atoi(builtin_name.substr(last + 1, builtin_name.size() - last - 1).c_str());
|
||||
}
|
||||
|
||||
void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &channels)
|
||||
void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels)
|
||||
{
|
||||
PointerRNA ptr;
|
||||
RNA_id_pointer_create((ID*)builtin_data, &ptr);
|
||||
@ -734,12 +734,14 @@ void BlenderSession::builtin_image_info(const string &builtin_name, void *builti
|
||||
is_float = b_image.is_float();
|
||||
width = b_image.size()[0];
|
||||
height = b_image.size()[1];
|
||||
depth = 1;
|
||||
channels = b_image.channels();
|
||||
}
|
||||
else {
|
||||
is_float = false;
|
||||
width = 0;
|
||||
height = 0;
|
||||
depth = 0;
|
||||
channels = 0;
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ protected:
|
||||
void do_write_update_render_tile(RenderTile& rtile, bool do_update_only);
|
||||
|
||||
int builtin_image_frame(const string &builtin_name);
|
||||
void builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &channels);
|
||||
void builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels);
|
||||
bool builtin_image_pixels(const string &builtin_name, void *builtin_data, unsigned char *pixels);
|
||||
bool builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels);
|
||||
};
|
||||
|
@ -105,7 +105,7 @@ public:
|
||||
|
||||
void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic)
|
||||
{
|
||||
kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height, interpolation);
|
||||
kernel_tex_copy(&kernel_globals, name, mem.data_pointer, mem.data_width, mem.data_height, mem.data_depth, interpolation);
|
||||
mem.device_pointer = mem.data_pointer;
|
||||
|
||||
stats.mem_alloc(mem.memory_size());
|
||||
|
@ -461,6 +461,8 @@ public:
|
||||
|
||||
void tex_alloc(const char *name, device_memory& mem, InterpolationType interpolation, bool periodic)
|
||||
{
|
||||
/* todo: support 3D textures, only CPU for now */
|
||||
|
||||
/* determine format */
|
||||
CUarray_format_enum format;
|
||||
size_t dsize = datatype_size(mem.data_type);
|
||||
|
@ -169,6 +169,7 @@ public:
|
||||
size_t data_size;
|
||||
size_t data_width;
|
||||
size_t data_height;
|
||||
size_t data_depth;
|
||||
|
||||
/* device pointer */
|
||||
device_ptr device_pointer;
|
||||
@ -195,6 +196,7 @@ public:
|
||||
data_size = 0;
|
||||
data_width = 0;
|
||||
data_height = 0;
|
||||
data_depth = 0;
|
||||
|
||||
assert(data_elements > 0);
|
||||
|
||||
@ -204,20 +206,21 @@ public:
|
||||
virtual ~device_vector() {}
|
||||
|
||||
/* vector functions */
|
||||
T *resize(size_t width, size_t height = 0)
|
||||
T *resize(size_t width, size_t height = 0, size_t depth = 0)
|
||||
{
|
||||
data_size = (height == 0)? width: width*height;
|
||||
data_size = width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
|
||||
data.resize(data_size);
|
||||
data_pointer = (device_ptr)&data[0];
|
||||
data_width = width;
|
||||
data_height = height;
|
||||
data_depth = depth;
|
||||
|
||||
return &data[0];
|
||||
}
|
||||
|
||||
T *copy(T *ptr, size_t width, size_t height = 0)
|
||||
T *copy(T *ptr, size_t width, size_t height = 0, size_t depth = 0)
|
||||
{
|
||||
T *mem = resize(width, height);
|
||||
T *mem = resize(width, height, depth);
|
||||
memcpy(mem, ptr, memory_size());
|
||||
return mem;
|
||||
}
|
||||
@ -230,13 +233,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void reference(T *ptr, size_t width, size_t height = 0)
|
||||
void reference(T *ptr, size_t width, size_t height = 0, size_t depth = 0)
|
||||
{
|
||||
data.clear();
|
||||
data_size = (height == 0)? width: width*height;
|
||||
data_size = width * ((height == 0)? 1: height) * ((depth == 0)? 1: depth);
|
||||
data_pointer = (device_ptr)ptr;
|
||||
data_width = width;
|
||||
data_height = height;
|
||||
data_depth = depth;
|
||||
}
|
||||
|
||||
void clear()
|
||||
@ -245,6 +249,7 @@ public:
|
||||
data_pointer = 0;
|
||||
data_width = 0;
|
||||
data_height = 0;
|
||||
data_depth = 0;
|
||||
data_size = 0;
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ public:
|
||||
void add(const device_memory& mem)
|
||||
{
|
||||
archive & mem.data_type & mem.data_elements & mem.data_size;
|
||||
archive & mem.data_width & mem.data_height & mem.device_pointer;
|
||||
archive & mem.data_width & mem.data_height & mem.data_depth & mem.device_pointer;
|
||||
}
|
||||
|
||||
template<typename T> void add(const T& data)
|
||||
@ -261,7 +261,7 @@ public:
|
||||
void read(network_device_memory& mem)
|
||||
{
|
||||
*archive & mem.data_type & mem.data_elements & mem.data_size;
|
||||
*archive & mem.data_width & mem.data_height & mem.device_pointer;
|
||||
*archive & mem.data_width & mem.data_height & mem.data_depth & mem.device_pointer;
|
||||
|
||||
mem.data_pointer = 0;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t s
|
||||
assert(0);
|
||||
}
|
||||
|
||||
void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, InterpolationType interpolation)
|
||||
void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, size_t depth, InterpolationType interpolation)
|
||||
{
|
||||
if(0) {
|
||||
}
|
||||
@ -63,6 +63,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
|
||||
tex->data = (float4*)mem;
|
||||
tex->width = width;
|
||||
tex->height = height;
|
||||
tex->depth = depth;
|
||||
tex->interpolation = interpolation;
|
||||
}
|
||||
}
|
||||
@ -79,6 +80,7 @@ void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t
|
||||
tex->data = (uchar4*)mem;
|
||||
tex->width = width;
|
||||
tex->height = height;
|
||||
tex->depth = depth;
|
||||
tex->interpolation = interpolation;
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ void *kernel_osl_memory(KernelGlobals *kg);
|
||||
bool kernel_osl_use(KernelGlobals *kg);
|
||||
|
||||
void kernel_const_copy(KernelGlobals *kg, const char *name, void *host, size_t size);
|
||||
void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, InterpolationType interpolation=INTERPOLATION_LINEAR);
|
||||
void kernel_tex_copy(KernelGlobals *kg, const char *name, device_ptr mem, size_t width, size_t height, size_t depth, InterpolationType interpolation=INTERPOLATION_LINEAR);
|
||||
|
||||
void kernel_cpu_path_trace(KernelGlobals *kg, float *buffer, unsigned int *rng_state,
|
||||
int sample, int x, int y, int offset, int stride);
|
||||
|
@ -99,6 +99,7 @@ template<typename T> struct texture_image {
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
int ix, iy, nix, niy;
|
||||
|
||||
if(interpolation == INTERPOLATION_CLOSEST) {
|
||||
frac(x*width, &ix);
|
||||
frac(y*height, &iy);
|
||||
@ -131,17 +132,84 @@ template<typename T> struct texture_image {
|
||||
nix = wrap_clamp(ix+1, width);
|
||||
niy = wrap_clamp(iy+1, height);
|
||||
}
|
||||
|
||||
float4 r = (1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width]);
|
||||
r += (1.0f - ty)*tx*read(data[nix + iy*width]);
|
||||
r += ty*(1.0f - tx)*read(data[ix + niy*width]);
|
||||
r += ty*tx*read(data[nix + niy*width]);
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
ccl_always_inline float4 interp_3d(float x, float y, float z, bool periodic = false)
|
||||
{
|
||||
if(!data)
|
||||
return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
int ix, iy, iz, nix, niy, niz;
|
||||
|
||||
if(interpolation == INTERPOLATION_CLOSEST) {
|
||||
frac(x*width, &ix);
|
||||
frac(y*height, &iy);
|
||||
frac(z*depth, &iz);
|
||||
|
||||
if(periodic) {
|
||||
ix = wrap_periodic(ix, width);
|
||||
iy = wrap_periodic(iy, height);
|
||||
iz = wrap_periodic(iz, depth);
|
||||
}
|
||||
else {
|
||||
ix = wrap_clamp(ix, width);
|
||||
iy = wrap_clamp(iy, height);
|
||||
iz = wrap_clamp(iz, depth);
|
||||
}
|
||||
|
||||
return read(data[ix + iy*width + iz*width*height]);
|
||||
}
|
||||
else {
|
||||
float tx = frac(x*width - 0.5f, &ix);
|
||||
float ty = frac(y*height - 0.5f, &iy);
|
||||
float tz = frac(z*depth - 0.5f, &iz);
|
||||
|
||||
if(periodic) {
|
||||
ix = wrap_periodic(ix, width);
|
||||
iy = wrap_periodic(iy, height);
|
||||
iz = wrap_periodic(iz, depth);
|
||||
|
||||
nix = wrap_periodic(ix+1, width);
|
||||
niy = wrap_periodic(iy+1, height);
|
||||
niz = wrap_periodic(iz+1, depth);
|
||||
}
|
||||
else {
|
||||
ix = wrap_clamp(ix, width);
|
||||
iy = wrap_clamp(iy, height);
|
||||
iz = wrap_clamp(iz, depth);
|
||||
|
||||
nix = wrap_clamp(ix+1, width);
|
||||
niy = wrap_clamp(iy+1, height);
|
||||
niz = wrap_clamp(iz+1, depth);
|
||||
}
|
||||
|
||||
float4 r;
|
||||
|
||||
r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + iz*width*height]);
|
||||
r += (1.0f - tz)*(1.0f - ty)*tx*read(data[nix + iy*width + iz*width*height]);
|
||||
r += (1.0f - tz)*ty*(1.0f - tx)*read(data[ix + niy*width + iz*width*height]);
|
||||
r += (1.0f - tz)*ty*tx*read(data[nix + niy*width + iz*width*height]);
|
||||
|
||||
r += tz*(1.0f - ty)*(1.0f - tx)*read(data[ix + iy*width + niz*width*height]);
|
||||
r += tz*(1.0f - ty)*tx*read(data[nix + iy*width + niz*width*height]);
|
||||
r += tz*ty*(1.0f - tx)*read(data[ix + niy*width + niz*width*height]);
|
||||
r += tz*ty*tx*read(data[nix + niy*width + niz*width*height]);
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
int interpolation;
|
||||
T *data;
|
||||
int width, height;
|
||||
int interpolation;
|
||||
int width, height, depth;
|
||||
};
|
||||
|
||||
typedef texture<float4> texture_float4;
|
||||
@ -161,6 +229,8 @@ typedef texture_image<uchar4> texture_image_uchar4;
|
||||
#define kernel_tex_fetch_m128i(tex, index) (kg->tex.fetch_m128i(index))
|
||||
#define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size))
|
||||
#define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y))
|
||||
#define kernel_tex_image_interp_3d(tex, x, y, z) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp_3d(x, y, z) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp_3d(x, y, z))
|
||||
|
||||
#define kernel_data (kg->__data)
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
@ -90,8 +90,8 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo
|
||||
|
||||
if(builtin_data) {
|
||||
if(builtin_image_info_cb) {
|
||||
int width, height, channels;
|
||||
builtin_image_info_cb(filename, builtin_data, is_float, width, height, channels);
|
||||
int width, height, depth, channels;
|
||||
builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels);
|
||||
}
|
||||
|
||||
if(is_float)
|
||||
@ -145,6 +145,13 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo
|
||||
return is_float;
|
||||
}
|
||||
|
||||
static bool image_equals(ImageManager::Image *image, const string& filename, void *builtin_data, bool interpolation)
|
||||
{
|
||||
return image->filename == filename &&
|
||||
image->builtin_data == builtin_data &&
|
||||
image->interpolation == interpolation;
|
||||
}
|
||||
|
||||
int ImageManager::add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear, InterpolationType interpolation)
|
||||
{
|
||||
Image *img;
|
||||
@ -156,7 +163,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
|
||||
if(is_float) {
|
||||
/* find existing image */
|
||||
for(slot = 0; slot < float_images.size(); slot++) {
|
||||
if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->interpolation == interpolation) {
|
||||
if(float_images[slot] && image_equals(float_images[slot], filename, builtin_data, interpolation)) {
|
||||
float_images[slot]->users++;
|
||||
return slot;
|
||||
}
|
||||
@ -192,7 +199,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
|
||||
}
|
||||
else {
|
||||
for(slot = 0; slot < images.size(); slot++) {
|
||||
if(images[slot] && images[slot]->filename == filename && images[slot]->interpolation == interpolation) {
|
||||
if(images[slot] && image_equals(images[slot], filename, builtin_data, interpolation)) {
|
||||
images[slot]->users++;
|
||||
return slot+tex_image_byte_start;
|
||||
}
|
||||
@ -233,22 +240,43 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
|
||||
return slot;
|
||||
}
|
||||
|
||||
void ImageManager::remove_image(int slot)
|
||||
{
|
||||
if(slot >= tex_image_byte_start) {
|
||||
slot -= tex_image_byte_start;
|
||||
|
||||
assert(images[slot] != NULL);
|
||||
|
||||
/* decrement user count */
|
||||
images[slot]->users--;
|
||||
assert(images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(images[slot]->users == 0)
|
||||
need_update = true;
|
||||
}
|
||||
else {
|
||||
/* decrement user count */
|
||||
float_images[slot]->users--;
|
||||
assert(float_images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(float_images[slot]->users == 0)
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageManager::remove_image(const string& filename, void *builtin_data, InterpolationType interpolation)
|
||||
{
|
||||
size_t slot;
|
||||
|
||||
for(slot = 0; slot < images.size(); slot++) {
|
||||
if(images[slot] && images[slot]->filename == filename && images[slot]->interpolation == interpolation && images[slot]->builtin_data == builtin_data) {
|
||||
/* decrement user count */
|
||||
images[slot]->users--;
|
||||
assert(images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(images[slot]->users == 0)
|
||||
need_update = true;
|
||||
|
||||
if(images[slot] && image_equals(images[slot], filename, builtin_data, interpolation)) {
|
||||
remove_image(slot+tex_image_byte_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -256,19 +284,8 @@ void ImageManager::remove_image(const string& filename, void *builtin_data, Inte
|
||||
if(slot == images.size()) {
|
||||
/* see if it's in a float texture slot */
|
||||
for(slot = 0; slot < float_images.size(); slot++) {
|
||||
if(float_images[slot] && float_images[slot]->filename == filename
|
||||
&& float_images[slot]->interpolation == interpolation
|
||||
&& float_images[slot]->builtin_data == builtin_data) {
|
||||
/* decrement user count */
|
||||
float_images[slot]->users--;
|
||||
assert(float_images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(float_images[slot]->users == 0)
|
||||
need_update = true;
|
||||
|
||||
if(float_images[slot] && image_equals(float_images[slot], filename, builtin_data, interpolation)) {
|
||||
remove_image(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -281,7 +298,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
return false;
|
||||
|
||||
ImageInput *in = NULL;
|
||||
int width, height, components;
|
||||
int width, height, depth, components;
|
||||
|
||||
if(!img->builtin_data) {
|
||||
/* load image from file through OIIO */
|
||||
@ -299,6 +316,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
|
||||
width = spec.width;
|
||||
height = spec.height;
|
||||
depth = spec.depth;
|
||||
components = spec.nchannels;
|
||||
}
|
||||
else {
|
||||
@ -307,7 +325,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
return false;
|
||||
|
||||
bool is_float;
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
|
||||
}
|
||||
|
||||
/* we only handle certain number of components */
|
||||
@ -321,15 +339,21 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
|
||||
/* read RGBA pixels */
|
||||
uchar *pixels = (uchar*)tex_img.resize(width, height);
|
||||
int scanlinesize = width*components*sizeof(uchar);
|
||||
uchar *pixels = (uchar*)tex_img.resize(width, height, depth);
|
||||
|
||||
if(in) {
|
||||
in->read_image(TypeDesc::UINT8,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
if(depth <= 1) {
|
||||
int scanlinesize = width*components*sizeof(uchar);
|
||||
|
||||
in->read_image(TypeDesc::UINT8,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
}
|
||||
else {
|
||||
in->read_image(TypeDesc::UINT8, (uchar*)pixels);
|
||||
}
|
||||
|
||||
in->close();
|
||||
delete in;
|
||||
@ -339,7 +363,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
|
||||
if(components == 2) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = pixels[i*2+1];
|
||||
pixels[i*4+2] = pixels[i*2+0];
|
||||
pixels[i*4+1] = pixels[i*2+0];
|
||||
@ -347,7 +371,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
}
|
||||
else if(components == 3) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 255;
|
||||
pixels[i*4+2] = pixels[i*3+2];
|
||||
pixels[i*4+1] = pixels[i*3+1];
|
||||
@ -355,7 +379,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
}
|
||||
else if(components == 1) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 255;
|
||||
pixels[i*4+2] = pixels[i];
|
||||
pixels[i*4+1] = pixels[i];
|
||||
@ -372,7 +396,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
return false;
|
||||
|
||||
ImageInput *in = NULL;
|
||||
int width, height, components;
|
||||
int width, height, depth, components;
|
||||
|
||||
if(!img->builtin_data) {
|
||||
/* load image from file through OIIO */
|
||||
@ -391,6 +415,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
/* we only handle certain number of components */
|
||||
width = spec.width;
|
||||
height = spec.height;
|
||||
depth = spec.depth;
|
||||
components = spec.nchannels;
|
||||
}
|
||||
else {
|
||||
@ -399,7 +424,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
return false;
|
||||
|
||||
bool is_float;
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
|
||||
}
|
||||
|
||||
if(!(components >= 1 && components <= 4)) {
|
||||
@ -411,15 +436,21 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
|
||||
/* read RGBA pixels */
|
||||
float *pixels = (float*)tex_img.resize(width, height);
|
||||
int scanlinesize = width*components*sizeof(float);
|
||||
float *pixels = (float*)tex_img.resize(width, height, depth);
|
||||
|
||||
if(in) {
|
||||
in->read_image(TypeDesc::FLOAT,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
if(depth <= 1) {
|
||||
int scanlinesize = width*components*sizeof(float);
|
||||
|
||||
in->read_image(TypeDesc::FLOAT,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
}
|
||||
else {
|
||||
in->read_image(TypeDesc::FLOAT, (uchar*)pixels);
|
||||
}
|
||||
|
||||
in->close();
|
||||
delete in;
|
||||
@ -429,7 +460,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
|
||||
if(components == 2) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = pixels[i*2+1];
|
||||
pixels[i*4+2] = pixels[i*2+0];
|
||||
pixels[i*4+1] = pixels[i*2+0];
|
||||
@ -437,7 +468,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
}
|
||||
else if(components == 3) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 1.0f;
|
||||
pixels[i*4+2] = pixels[i*3+2];
|
||||
pixels[i*4+1] = pixels[i*3+1];
|
||||
@ -445,7 +476,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
}
|
||||
else if(components == 1) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 1.0f;
|
||||
pixels[i*4+2] = pixels[i];
|
||||
pixels[i*4+1] = pixels[i];
|
||||
@ -460,9 +491,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
|
||||
{
|
||||
if(progress->get_cancel())
|
||||
return;
|
||||
if(osl_texture_system)
|
||||
return;
|
||||
|
||||
|
||||
Image *img;
|
||||
bool is_float;
|
||||
|
||||
@ -475,6 +504,9 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
|
||||
is_float = true;
|
||||
}
|
||||
|
||||
if(osl_texture_system && !img->builtin_data)
|
||||
return;
|
||||
|
||||
if(is_float) {
|
||||
string filename = path_filename(float_images[slot]->filename);
|
||||
progress->set_status("Updating Images", "Loading " + filename);
|
||||
@ -556,7 +588,7 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl
|
||||
}
|
||||
|
||||
if(img) {
|
||||
if(osl_texture_system) {
|
||||
if(osl_texture_system && !img->builtin_data) {
|
||||
#ifdef WITH_OSL
|
||||
ustring filename(images[slot]->filename);
|
||||
((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
|
||||
@ -606,7 +638,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
|
||||
device_free_image(device, dscene, slot + tex_image_byte_start);
|
||||
}
|
||||
else if(images[slot]->need_load) {
|
||||
if(!osl_texture_system)
|
||||
if(!osl_texture_system || images[slot]->builtin_data)
|
||||
pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + tex_image_byte_start, &progress));
|
||||
}
|
||||
}
|
||||
@ -619,7 +651,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
|
||||
device_free_image(device, dscene, slot);
|
||||
}
|
||||
else if(float_images[slot]->need_load) {
|
||||
if(!osl_texture_system)
|
||||
if(!osl_texture_system || float_images[slot]->builtin_data)
|
||||
pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress));
|
||||
}
|
||||
}
|
||||
@ -657,6 +689,7 @@ void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progr
|
||||
|
||||
device_vector<uchar4>& tex_img = dscene->tex_image[slot];
|
||||
|
||||
/* todo: support 3D textures, only CPU for now */
|
||||
|
||||
/* The image options are packed
|
||||
bit 0 -> periodic
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
~ImageManager();
|
||||
|
||||
int add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear, InterpolationType interpolation);
|
||||
void remove_image(int slot);
|
||||
void remove_image(const string& filename, void *builtin_data, InterpolationType interpolation);
|
||||
bool is_float_image(const string& filename, void *builtin_data, bool& is_linear);
|
||||
|
||||
@ -63,15 +64,9 @@ public:
|
||||
|
||||
bool need_update;
|
||||
|
||||
boost::function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &channels)> builtin_image_info_cb;
|
||||
boost::function<void(const string &filename, void *data, bool &is_float, int &width, int &height, int &depth, int &channels)> builtin_image_info_cb;
|
||||
boost::function<bool(const string &filename, void *data, unsigned char *pixels)> builtin_image_pixels_cb;
|
||||
boost::function<bool(const string &filename, void *data, float *pixels)> builtin_image_float_pixels_cb;
|
||||
private:
|
||||
int tex_num_images;
|
||||
int tex_num_float_images;
|
||||
int tex_image_byte_start;
|
||||
thread_mutex device_mutex;
|
||||
int animation_frame;
|
||||
|
||||
struct Image {
|
||||
string filename;
|
||||
@ -84,6 +79,13 @@ private:
|
||||
int users;
|
||||
};
|
||||
|
||||
private:
|
||||
int tex_num_images;
|
||||
int tex_num_float_images;
|
||||
int tex_image_byte_start;
|
||||
thread_mutex device_mutex;
|
||||
int animation_frame;
|
||||
|
||||
vector<Image*> images;
|
||||
vector<Image*> float_images;
|
||||
void *osl_texture_system;
|
||||
|
Loading…
Reference in New Issue
Block a user