Compare commits
75 Commits
temp-ui-cp
...
temp-udim-
Author | SHA1 | Date | |
---|---|---|---|
e704c78d87 | |||
3c643440a3 | |||
ccbfdd05d7 | |||
579bf61a97 | |||
8eee1a312b | |||
82e2c9ff31 | |||
215f1c928e | |||
80afab3d82 | |||
6cab58dfc2 | |||
2b74af08eb | |||
395f6bcc60 | |||
d87a227ce1 | |||
54f50bd3cc | |||
962311358b | |||
5b6df588f2 | |||
cd20a1399e | |||
19db478bc5 | |||
b33d272e91 | |||
f24647bd4d | |||
f354744713 | |||
fbb0815fd7 | |||
b0c7dda4a7 | |||
d5e849339b | |||
7d05a1035a | |||
7c34a379fa | |||
ea9d1a06aa | |||
acfbd76f85 | |||
c6e8dd331b | |||
b3da4f8fd5 | |||
82e2ea8fce | |||
b6a3231ba5 | |||
9b745515e4 | |||
a725059074 | |||
59428ec169 | |||
28504a99c2 | |||
120300708f | |||
ab629a95f0 | |||
c383935a72 | |||
852969826f | |||
67097adad6 | |||
4b69034172 | |||
8b75f609e4 | |||
d8ed157bd2 | |||
27cd60017f | |||
e93ce4f5e0 | |||
4e27014103 | |||
8325f7f0b4 | |||
37c89eb3da | |||
336fbdf5fc | |||
d9cd8df242 | |||
bc05599bd0 | |||
79c58d27e9 | |||
b91706368f | |||
f388b31ad1 | |||
4875f41ea6 | |||
d3d0c8febc | |||
7118317e9f | |||
b7cc2dbdce | |||
e1e975aeb8 | |||
3451769219 | |||
24318440eb | |||
799303dd87 | |||
005d1d0933 | |||
9fc9376004 | |||
cc4defac04 | |||
1d40503210 | |||
d6f9e6bf0c | |||
94d0cbf127 | |||
e2e80ec649 | |||
62550b490a | |||
25a4363ed4 | |||
5c62468e4b | |||
89c0dc4ebd | |||
a5732a1de4 | |||
9220f3b64f |
@@ -348,6 +348,7 @@ static void create_mesh_volume_attribute(BL::Object& b_ob,
|
||||
Attribute::standard_name(std),
|
||||
b_ob.ptr.data,
|
||||
animated,
|
||||
0,
|
||||
frame,
|
||||
INTERPOLATION_LINEAR,
|
||||
EXTENSION_CLIP,
|
||||
|
@@ -142,8 +142,8 @@ void BlenderSession::create_session()
|
||||
|
||||
/* setup callbacks for builtin image support */
|
||||
scene->image_manager->builtin_image_info_cb = function_bind(&BlenderSession::builtin_image_info, this, _1, _2, _3);
|
||||
scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5);
|
||||
scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5);
|
||||
scene->image_manager->builtin_image_pixels_cb = function_bind(&BlenderSession::builtin_image_pixels, this, _1, _2, _3, _4, _5, _6);
|
||||
scene->image_manager->builtin_image_float_pixels_cb = function_bind(&BlenderSession::builtin_image_float_pixels, this, _1, _2, _3, _4, _5, _6);
|
||||
|
||||
session->scene = scene;
|
||||
|
||||
@@ -1119,6 +1119,7 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
|
||||
|
||||
bool BlenderSession::builtin_image_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
unsigned char *pixels,
|
||||
const size_t pixels_size,
|
||||
const bool free_cache)
|
||||
@@ -1137,7 +1138,7 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
|
||||
const int height = b_image.size()[1];
|
||||
const int channels = b_image.channels();
|
||||
|
||||
unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame);
|
||||
unsigned char *image_pixels = image_get_pixels_for_frame(b_image, frame, tile);
|
||||
const size_t num_pixels = ((size_t)width) * height;
|
||||
|
||||
if(image_pixels && num_pixels * channels == pixels_size) {
|
||||
@@ -1182,6 +1183,7 @@ bool BlenderSession::builtin_image_pixels(const string &builtin_name,
|
||||
|
||||
bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
float *pixels,
|
||||
const size_t pixels_size,
|
||||
const bool free_cache)
|
||||
@@ -1204,7 +1206,7 @@ bool BlenderSession::builtin_image_float_pixels(const string &builtin_name,
|
||||
const int channels = b_image.channels();
|
||||
|
||||
float *image_pixels;
|
||||
image_pixels = image_get_float_pixels_for_frame(b_image, frame);
|
||||
image_pixels = image_get_float_pixels_for_frame(b_image, frame, tile);
|
||||
const size_t num_pixels = ((size_t)width) * height;
|
||||
|
||||
if(image_pixels && num_pixels * channels == pixels_size) {
|
||||
|
@@ -160,11 +160,13 @@ protected:
|
||||
ImageMetaData& metadata);
|
||||
bool builtin_image_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
unsigned char *pixels,
|
||||
const size_t pixels_size,
|
||||
const bool free_cache);
|
||||
bool builtin_image_float_pixels(const string &builtin_name,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
float *pixels,
|
||||
const size_t pixels_size,
|
||||
const bool free_cache);
|
||||
|
@@ -670,6 +670,12 @@ static ShaderNode *add_node(Scene *scene,
|
||||
image->animated = b_image_node.image_user().use_auto_refresh();
|
||||
image->use_alpha = b_image.use_alpha();
|
||||
|
||||
image->tiles.clear();
|
||||
BL::Image::tiles_iterator b_iter;
|
||||
for(b_image.tiles.begin(b_iter); b_iter != b_image.tiles.end(); ++b_iter) {
|
||||
image->tiles.push_back(b_iter->tile_number());
|
||||
}
|
||||
|
||||
/* TODO: restore */
|
||||
/* TODO(sergey): Does not work properly when we change builtin type. */
|
||||
#if 0
|
||||
@@ -884,6 +890,7 @@ static ShaderNode *add_node(Scene *scene,
|
||||
scene->image_manager->tag_reload_image(
|
||||
point_density->filename.string(),
|
||||
point_density->builtin_data,
|
||||
0,
|
||||
point_density->interpolation,
|
||||
EXTENSION_CLIP,
|
||||
true);
|
||||
@@ -1245,7 +1252,7 @@ void BlenderSync::sync_materials(BL::Depsgraph& b_depsgraph, bool update_all)
|
||||
|
||||
/* test if we need to sync */
|
||||
if(shader_map.sync(&shader, b_mat) || shader->need_sync_object || update_all) {
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
ShaderGraph *graph = new ShaderGraph(shader);
|
||||
|
||||
shader->name = b_mat.name().c_str();
|
||||
shader->pass_id = b_mat.pass_index();
|
||||
@@ -1320,7 +1327,7 @@ void BlenderSync::sync_world(BL::Depsgraph& b_depsgraph, bool update_all)
|
||||
|
||||
if(world_recalc || update_all || b_world.ptr.data != world_map) {
|
||||
Shader *shader = scene->default_background;
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
ShaderGraph *graph = new ShaderGraph(shader);
|
||||
|
||||
/* create nodes */
|
||||
if(b_world && b_world.use_nodes() && b_world.node_tree()) {
|
||||
@@ -1418,7 +1425,7 @@ void BlenderSync::sync_lights(BL::Depsgraph& b_depsgraph, bool update_all)
|
||||
|
||||
/* test if we need to sync */
|
||||
if(shader_map.sync(&shader, b_light) || update_all) {
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
ShaderGraph *graph = new ShaderGraph(shader);
|
||||
|
||||
/* create nodes */
|
||||
if(b_light.use_nodes() && b_light.node_tree()) {
|
||||
|
@@ -620,6 +620,8 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
|
||||
|
||||
params.bvh_layout = DebugFlags().cpu.bvh_layout;
|
||||
|
||||
params.background = background;
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@@ -34,8 +34,8 @@ extern "C" {
|
||||
size_t BLI_timecode_string_from_time_simple(char *str, size_t maxlen, double time_seconds);
|
||||
void BKE_image_user_frame_calc(void *iuser, int cfra, int fieldnr);
|
||||
void BKE_image_user_file_path(void *iuser, void *ima, char *path);
|
||||
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame);
|
||||
float *BKE_image_get_float_pixels_for_frame(void *image, int frame);
|
||||
unsigned char *BKE_image_get_pixels_for_frame(void *image, int frame, int tile);
|
||||
float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
@@ -220,8 +220,15 @@ static inline string image_user_file_path(BL::ImageUser& iuser,
|
||||
int cfra)
|
||||
{
|
||||
char filepath[1024];
|
||||
iuser.tile(0);
|
||||
BKE_image_user_frame_calc(iuser.ptr.data, cfra, 0);
|
||||
BKE_image_user_file_path(iuser.ptr.data, ima.ptr.data, filepath);
|
||||
if(ima.source() == BL::Image::source_TILED) {
|
||||
char *udim_id = strstr(filepath, "1001");
|
||||
if(udim_id) {
|
||||
memcpy(udim_id, "%04d", 4);
|
||||
}
|
||||
}
|
||||
return string(filepath);
|
||||
}
|
||||
|
||||
@@ -232,15 +239,15 @@ static inline int image_user_frame_number(BL::ImageUser& iuser, int cfra)
|
||||
}
|
||||
|
||||
static inline unsigned char *image_get_pixels_for_frame(BL::Image& image,
|
||||
int frame)
|
||||
int frame, int tile)
|
||||
{
|
||||
return BKE_image_get_pixels_for_frame(image.ptr.data, frame);
|
||||
return BKE_image_get_pixels_for_frame(image.ptr.data, frame, tile);
|
||||
}
|
||||
|
||||
static inline float *image_get_float_pixels_for_frame(BL::Image& image,
|
||||
int frame)
|
||||
int frame, int tile)
|
||||
{
|
||||
return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame);
|
||||
return BKE_image_get_float_pixels_for_frame(image.ptr.data, frame, tile);
|
||||
}
|
||||
|
||||
/* Utilities */
|
||||
|
@@ -277,7 +277,7 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
|
||||
# endif /* NODES_FEATURE(NODE_FEATURE_BUMP) */
|
||||
# ifdef __TEXTURES__
|
||||
case NODE_TEX_IMAGE:
|
||||
svm_node_tex_image(kg, sd, stack, node);
|
||||
svm_node_tex_image(kg, sd, stack, node, &offset);
|
||||
break;
|
||||
case NODE_TEX_IMAGE_BOX:
|
||||
svm_node_tex_image_box(kg, sd, stack, node);
|
||||
|
@@ -18,6 +18,9 @@ CCL_NAMESPACE_BEGIN
|
||||
|
||||
ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y, uint srgb, uint use_alpha)
|
||||
{
|
||||
if(id == -1) {
|
||||
return make_float4(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
|
||||
}
|
||||
float4 r = kernel_tex_image_interp(kg, id, x, y);
|
||||
const float alpha = r.w;
|
||||
|
||||
@@ -46,9 +49,8 @@ ccl_device_inline float3 texco_remap_square(float3 co)
|
||||
return (co - make_float3(0.5f, 0.5f, 0.5f)) * 2.0f;
|
||||
}
|
||||
|
||||
ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
|
||||
ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
|
||||
{
|
||||
uint id = node.y;
|
||||
uint co_offset, out_offset, alpha_offset, srgb;
|
||||
|
||||
decode_node_uchar4(node.z, &co_offset, &out_offset, &alpha_offset, &srgb);
|
||||
@@ -67,6 +69,38 @@ ccl_device void svm_node_tex_image(KernelGlobals *kg, ShaderData *sd, float *sta
|
||||
else {
|
||||
tex_co = make_float2(co.x, co.y);
|
||||
}
|
||||
|
||||
int id = -1;
|
||||
if(node.y > 0) {
|
||||
uint num_nodes = node.y;
|
||||
int next_offset = (*offset) + num_nodes;
|
||||
if(tex_co.x >= 0.0f && tex_co.y < 10.0f && tex_co.y >= 0.0f) {
|
||||
int tx = (int) tex_co.x;
|
||||
int ty = (int) tex_co.y;
|
||||
int tile = ty*10 + tx;
|
||||
for(int i = 0; i < num_nodes; i++) {
|
||||
uint4 node = read_node(kg, offset);
|
||||
if(node.x == tile) {
|
||||
id = node.y;
|
||||
break;
|
||||
}
|
||||
if(node.z == tile) {
|
||||
id = node.w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(id != -1) {
|
||||
tex_co.x -= tx;
|
||||
tex_co.y -= ty;
|
||||
}
|
||||
}
|
||||
*offset = next_offset;
|
||||
}
|
||||
else {
|
||||
id = read_node(kg, offset).y;
|
||||
}
|
||||
|
||||
float4 f = svm_image_texture(kg, id, tex_co.x, tex_co.y, srgb, use_alpha);
|
||||
|
||||
if(stack_valid(out_offset))
|
||||
|
@@ -193,7 +193,8 @@ bool ShaderNode::equals(const ShaderNode& other)
|
||||
|
||||
/* Graph */
|
||||
|
||||
ShaderGraph::ShaderGraph()
|
||||
ShaderGraph::ShaderGraph(Shader *shader)
|
||||
: shader(shader)
|
||||
{
|
||||
finalized = false;
|
||||
simplified = false;
|
||||
@@ -557,7 +558,7 @@ void ShaderGraph::constant_fold(Scene *scene)
|
||||
void ShaderGraph::simplify_settings(Scene *scene)
|
||||
{
|
||||
foreach(ShaderNode *node, nodes) {
|
||||
node->simplify_settings(scene);
|
||||
node->simplify_settings(scene, shader);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -147,7 +147,7 @@ public:
|
||||
/* Simplify settings used by artists to the ones which are simpler to
|
||||
* evaluate in the kernel but keep the final result unchanged.
|
||||
*/
|
||||
virtual void simplify_settings(Scene * /*scene*/) {};
|
||||
virtual void simplify_settings(Scene * /*scene*/, Shader * /*shader*/) {};
|
||||
|
||||
virtual bool has_surface_emission() { return false; }
|
||||
virtual bool has_surface_transparent() { return false; }
|
||||
@@ -246,8 +246,9 @@ public:
|
||||
bool finalized;
|
||||
bool simplified;
|
||||
string displacement_hash;
|
||||
Shader *shader;
|
||||
|
||||
ShaderGraph();
|
||||
ShaderGraph(Shader *shader);
|
||||
~ShaderGraph();
|
||||
|
||||
ShaderNode *add(ShaderNode *node);
|
||||
|
@@ -278,12 +278,14 @@ bool ImageManager::get_image_metadata(const string& filename,
|
||||
static bool image_equals(ImageManager::Image *image,
|
||||
const string& filename,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
InterpolationType interpolation,
|
||||
ExtensionType extension,
|
||||
bool use_alpha)
|
||||
{
|
||||
return image->filename == filename &&
|
||||
image->builtin_data == builtin_data &&
|
||||
image->tile == tile &&
|
||||
image->interpolation == interpolation &&
|
||||
image->extension == extension &&
|
||||
image->use_alpha == use_alpha;
|
||||
@@ -292,6 +294,7 @@ static bool image_equals(ImageManager::Image *image,
|
||||
int ImageManager::add_image(const string& filename,
|
||||
void *builtin_data,
|
||||
bool animated,
|
||||
int tile,
|
||||
float frame,
|
||||
InterpolationType interpolation,
|
||||
ExtensionType extension,
|
||||
@@ -322,6 +325,7 @@ int ImageManager::add_image(const string& filename,
|
||||
if(img && image_equals(img,
|
||||
filename,
|
||||
builtin_data,
|
||||
tile,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha))
|
||||
@@ -370,6 +374,7 @@ int ImageManager::add_image(const string& filename,
|
||||
img->metadata = metadata;
|
||||
img->need_load = true;
|
||||
img->animated = animated;
|
||||
img->tile = tile;
|
||||
img->frame = frame;
|
||||
img->interpolation = interpolation;
|
||||
img->extension = extension;
|
||||
@@ -406,6 +411,7 @@ void ImageManager::remove_image(int flat_slot)
|
||||
|
||||
void ImageManager::remove_image(const string& filename,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
InterpolationType interpolation,
|
||||
ExtensionType extension,
|
||||
bool use_alpha)
|
||||
@@ -417,6 +423,7 @@ void ImageManager::remove_image(const string& filename,
|
||||
if(images[type][slot] && image_equals(images[type][slot],
|
||||
filename,
|
||||
builtin_data,
|
||||
tile,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha))
|
||||
@@ -434,6 +441,7 @@ void ImageManager::remove_image(const string& filename,
|
||||
*/
|
||||
void ImageManager::tag_reload_image(const string& filename,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
InterpolationType interpolation,
|
||||
ExtensionType extension,
|
||||
bool use_alpha)
|
||||
@@ -443,6 +451,7 @@ void ImageManager::tag_reload_image(const string& filename,
|
||||
if(images[type][slot] && image_equals(images[type][slot],
|
||||
filename,
|
||||
builtin_data,
|
||||
tile,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha))
|
||||
@@ -581,6 +590,7 @@ bool ImageManager::file_load_image(Image *img,
|
||||
if(FileFormat == TypeDesc::FLOAT) {
|
||||
builtin_image_float_pixels_cb(img->filename,
|
||||
img->builtin_data,
|
||||
img->tile,
|
||||
(float*)&pixels[0],
|
||||
num_pixels * components,
|
||||
img->metadata.builtin_free_cache);
|
||||
@@ -588,6 +598,7 @@ bool ImageManager::file_load_image(Image *img,
|
||||
else if(FileFormat == TypeDesc::UINT8) {
|
||||
builtin_image_pixels_cb(img->filename,
|
||||
img->builtin_data,
|
||||
img->tile,
|
||||
(uchar*)&pixels[0],
|
||||
num_pixels * components,
|
||||
img->metadata.builtin_free_cache);
|
||||
|
@@ -53,6 +53,7 @@ public:
|
||||
int add_image(const string& filename,
|
||||
void *builtin_data,
|
||||
bool animated,
|
||||
int tile,
|
||||
float frame,
|
||||
InterpolationType interpolation,
|
||||
ExtensionType extension,
|
||||
@@ -61,11 +62,13 @@ public:
|
||||
void remove_image(int flat_slot);
|
||||
void remove_image(const string& filename,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
InterpolationType interpolation,
|
||||
ExtensionType extension,
|
||||
bool use_alpha);
|
||||
void tag_reload_image(const string& filename,
|
||||
void *builtin_data,
|
||||
int tile,
|
||||
InterpolationType interpolation,
|
||||
ExtensionType extension,
|
||||
bool use_alpha);
|
||||
@@ -107,11 +110,13 @@ public:
|
||||
ImageMetaData& metadata)> builtin_image_info_cb;
|
||||
function<bool(const string &filename,
|
||||
void *data,
|
||||
int tile,
|
||||
unsigned char *pixels,
|
||||
const size_t pixels_size,
|
||||
const bool free_cache)> builtin_image_pixels_cb;
|
||||
function<bool(const string &filename,
|
||||
void *data,
|
||||
int tile,
|
||||
float *pixels,
|
||||
const size_t pixels_size,
|
||||
const bool free_cache)> builtin_image_float_pixels_cb;
|
||||
@@ -125,6 +130,7 @@ public:
|
||||
bool need_load;
|
||||
bool animated;
|
||||
float frame;
|
||||
int tile;
|
||||
InterpolationType interpolation;
|
||||
ExtensionType extension;
|
||||
|
||||
|
@@ -555,9 +555,13 @@ void LightManager::device_update_background(Device *device,
|
||||
if(node->type == EnvironmentTextureNode::node_type) {
|
||||
EnvironmentTextureNode *env = (EnvironmentTextureNode*) node;
|
||||
ImageMetaData metadata;
|
||||
if(env->image_manager && env->image_manager->get_image_metadata(env->slot, metadata)) {
|
||||
res.x = max(res.x, metadata.width);
|
||||
res.y = max(res.y, metadata.height);
|
||||
if(env->image_manager) {
|
||||
foreach(int slot, env->slots) {
|
||||
if(env->image_manager->get_image_metadata(slot, metadata)) {
|
||||
res.x = max(res.x, metadata.width);
|
||||
res.y = max(res.y, metadata.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -662,6 +662,61 @@ void Mesh::add_subd_face(int* corners, int num_corners, int shader_, bool smooth
|
||||
subd_faces.push_back_reserved(face);
|
||||
}
|
||||
|
||||
static void get_uv_tiles_from_attribute(Attribute *attr, int num, vector<bool> &tiles)
|
||||
{
|
||||
if(!attr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float3 *uv = attr->data_float3();
|
||||
int size = tiles.size();
|
||||
for(int i = 0; i < num; i++, uv++) {
|
||||
float u = uv->x, v = uv->y;
|
||||
|
||||
if(u < 0.0f || v < 0.0f || u > 10.0f) continue;
|
||||
|
||||
int x = (int) u, y = (int) v;
|
||||
|
||||
/* Be conservative in corners - precisely touching the right-upper corner of a tile
|
||||
* should not load its right-upper neighbor as well. */
|
||||
if(x && (u == x)) x--;
|
||||
if(y && (v == y)) y--;
|
||||
|
||||
int id = y*10 + x;
|
||||
if(id >= size) {
|
||||
tiles.resize(id+1);
|
||||
size = id;
|
||||
}
|
||||
tiles[id] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::get_uv_tiles(ustring map, vector<bool> &tiles)
|
||||
{
|
||||
if(map.empty()) {
|
||||
get_uv_tiles_from_attribute(attributes.find(ATTR_STD_UV),
|
||||
num_triangles()*3,
|
||||
tiles);
|
||||
get_uv_tiles_from_attribute(subd_attributes.find(ATTR_STD_UV),
|
||||
subd_face_corners.size() + num_ngons,
|
||||
tiles);
|
||||
get_uv_tiles_from_attribute(curve_attributes.find(ATTR_STD_UV),
|
||||
num_curves(),
|
||||
tiles);
|
||||
}
|
||||
else {
|
||||
get_uv_tiles_from_attribute(attributes.find(map),
|
||||
num_triangles()*3,
|
||||
tiles);
|
||||
get_uv_tiles_from_attribute(subd_attributes.find(map),
|
||||
subd_face_corners.size() + num_ngons,
|
||||
tiles);
|
||||
get_uv_tiles_from_attribute(curve_attributes.find(map),
|
||||
num_curves(),
|
||||
tiles);
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::compute_bounds()
|
||||
{
|
||||
BoundBox bnds = BoundBox::empty;
|
||||
@@ -1996,8 +2051,7 @@ void MeshManager::device_update_displacement_images(Device *device,
|
||||
}
|
||||
|
||||
ImageSlotTextureNode *image_node = static_cast<ImageSlotTextureNode*>(node);
|
||||
int slot = image_node->slot;
|
||||
if(slot != -1) {
|
||||
foreach(int slot, image_node->slots) {
|
||||
bump_images.insert(slot);
|
||||
}
|
||||
}
|
||||
|
@@ -280,6 +280,8 @@ public:
|
||||
void add_vertex_normals();
|
||||
void add_undisplaced();
|
||||
|
||||
void get_uv_tiles(ustring map, vector<bool> &tiles);
|
||||
|
||||
void pack_shaders(Scene *scene, uint *shader);
|
||||
void pack_normals(float4 *vnormal);
|
||||
void pack_verts(const vector<uint>& tri_prim_index,
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "render/image.h"
|
||||
#include "render/integrator.h"
|
||||
#include "render/light.h"
|
||||
#include "render/mesh.h"
|
||||
#include "render/nodes.h"
|
||||
#include "render/scene.h"
|
||||
#include "render/svm.h"
|
||||
@@ -249,21 +250,19 @@ ImageTextureNode::ImageTextureNode()
|
||||
: ImageSlotTextureNode(node_type)
|
||||
{
|
||||
image_manager = NULL;
|
||||
slot = -1;
|
||||
is_float = -1;
|
||||
is_float = false;
|
||||
is_linear = false;
|
||||
builtin_data = NULL;
|
||||
animated = false;
|
||||
tiles.push_back(0);
|
||||
}
|
||||
|
||||
ImageTextureNode::~ImageTextureNode()
|
||||
{
|
||||
if(image_manager) {
|
||||
image_manager->remove_image(filename.string(),
|
||||
builtin_data,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha);
|
||||
foreach(int slot, slots) {
|
||||
image_manager->remove_image(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,12 +270,55 @@ ShaderNode *ImageTextureNode::clone() const
|
||||
{
|
||||
ImageTextureNode *node = new ImageTextureNode(*this);
|
||||
node->image_manager = NULL;
|
||||
node->slot = -1;
|
||||
node->is_float = -1;
|
||||
node->slots.clear();
|
||||
node->is_float = false;
|
||||
node->is_linear = false;
|
||||
return node;
|
||||
}
|
||||
|
||||
void ImageTextureNode::simplify_settings(Scene *scene, Shader *shader)
|
||||
{
|
||||
if(!scene->params.background) {
|
||||
/* During interactive renders, all tiles are loaded.
|
||||
* While we could support updating this when UVs change, that could lead
|
||||
* to annoying interruptions when loading images while editing UVs. */
|
||||
return;
|
||||
}
|
||||
|
||||
ShaderInput *vector_in = input("Vector");
|
||||
ustring attribute;
|
||||
if(vector_in->link) {
|
||||
ShaderNode *node = vector_in->link->parent;
|
||||
if(node->type == UVMapNode::node_type) {
|
||||
UVMapNode *uvmap = (UVMapNode*) node;
|
||||
attribute = uvmap->attribute;
|
||||
}
|
||||
else if(node->type == TextureCoordinateNode::node_type) {
|
||||
if(vector_in->link != node->output("UV")) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ccl::vector<bool> used_tiles;
|
||||
foreach(Mesh *mesh, scene->meshes) {
|
||||
if(std::find(mesh->used_shaders.begin(), mesh->used_shaders.end(), shader) != mesh->used_shaders.end()) {
|
||||
mesh->get_uv_tiles(attribute, used_tiles);
|
||||
}
|
||||
}
|
||||
|
||||
ccl::vector<int> new_tiles;
|
||||
foreach(int tile, tiles) {
|
||||
if (tile < used_tiles.size() && used_tiles[tile]) {
|
||||
new_tiles.push_back(tile);
|
||||
}
|
||||
}
|
||||
tiles.swap(new_tiles);
|
||||
}
|
||||
|
||||
void ImageTextureNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
{
|
||||
#ifdef WITH_PTEX
|
||||
@@ -299,27 +341,52 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
|
||||
ShaderOutput *alpha_out = output("Alpha");
|
||||
|
||||
image_manager = compiler.image_manager;
|
||||
if(is_float == -1) {
|
||||
ImageMetaData metadata;
|
||||
slot = image_manager->add_image(filename.string(),
|
||||
builtin_data,
|
||||
animated,
|
||||
0,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha,
|
||||
metadata);
|
||||
is_float = metadata.is_float;
|
||||
is_linear = metadata.is_linear;
|
||||
if(slots.size() < tiles.size()) {
|
||||
slots.clear();
|
||||
foreach(int tile, tiles) {
|
||||
string tile_name;
|
||||
if(tiles.size() == 1) {
|
||||
tile_name = filename.string();
|
||||
}
|
||||
else {
|
||||
tile_name = string_printf(filename.c_str(), 1001 + tile);
|
||||
}
|
||||
printf("Loading %s\n", tile_name.c_str());
|
||||
ImageMetaData metadata;
|
||||
slots.push_back(image_manager->add_image(tile_name,
|
||||
builtin_data,
|
||||
animated,
|
||||
tile,
|
||||
0,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha,
|
||||
metadata));
|
||||
if(tile == 0) {
|
||||
is_float = metadata.is_float;
|
||||
is_linear = metadata.is_linear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(slot != -1) {
|
||||
bool has_image = false;
|
||||
foreach(int slot, slots) {
|
||||
if(slot != -1) {
|
||||
has_image = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(has_image) {
|
||||
int num_nodes = divide_up(slots.size(), 2);
|
||||
int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
|
||||
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
|
||||
|
||||
/* TODO(lukas): Avoid extra node for common case of only one tile. */
|
||||
|
||||
if(projection != NODE_IMAGE_PROJ_BOX) {
|
||||
compiler.add_node(NODE_TEX_IMAGE,
|
||||
slot,
|
||||
num_nodes,
|
||||
compiler.encode_uchar4(
|
||||
vector_offset,
|
||||
compiler.stack_assign_if_linked(color_out),
|
||||
@@ -329,7 +396,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
|
||||
}
|
||||
else {
|
||||
compiler.add_node(NODE_TEX_IMAGE_BOX,
|
||||
slot,
|
||||
num_nodes,
|
||||
compiler.encode_uchar4(
|
||||
vector_offset,
|
||||
compiler.stack_assign_if_linked(color_out),
|
||||
@@ -338,6 +405,21 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
|
||||
__float_as_int(projection_blend));
|
||||
}
|
||||
|
||||
for(int i = 0; i < num_nodes; i++) {
|
||||
int4 node;
|
||||
node.x = tiles[2*i];
|
||||
node.y = slots[2*i];
|
||||
if(2*i+1 < slots.size()) {
|
||||
node.z = tiles[2*i+1];
|
||||
node.w = slots[2*i+1];
|
||||
}
|
||||
else {
|
||||
node.z = -1;
|
||||
node.w = -1;
|
||||
}
|
||||
compiler.add_node(node.x, node.y, node.z, node.w);
|
||||
}
|
||||
|
||||
tex_mapping.compile_end(compiler, vector_in, vector_offset);
|
||||
}
|
||||
else {
|
||||
@@ -360,26 +442,28 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
|
||||
tex_mapping.compile(compiler);
|
||||
|
||||
image_manager = compiler.image_manager;
|
||||
if(is_float == -1) {
|
||||
if(slots.size() == 0) {
|
||||
ImageMetaData metadata;
|
||||
if(builtin_data == NULL) {
|
||||
image_manager->get_image_metadata(filename.string(), NULL, metadata);
|
||||
slots.push_back(-1);
|
||||
}
|
||||
else {
|
||||
slot = image_manager->add_image(filename.string(),
|
||||
builtin_data,
|
||||
animated,
|
||||
0,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha,
|
||||
metadata);
|
||||
slots.push_back(image_manager->add_image(filename.string(),
|
||||
builtin_data,
|
||||
animated,
|
||||
0,
|
||||
0,
|
||||
interpolation,
|
||||
extension,
|
||||
use_alpha,
|
||||
metadata));
|
||||
}
|
||||
is_float = metadata.is_float;
|
||||
is_linear = metadata.is_linear;
|
||||
}
|
||||
|
||||
if(slot == -1) {
|
||||
if(slots[0] == -1) {
|
||||
compiler.parameter(this, "filename");
|
||||
}
|
||||
else {
|
||||
@@ -389,7 +473,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
|
||||
* "@i<slot_number>" and check whether file name matches this
|
||||
* mask in the OSLRenderServices::texture().
|
||||
*/
|
||||
compiler.parameter("filename", string_printf("@i%d", slot).c_str());
|
||||
compiler.parameter("filename", string_printf("@i%d", slots[0]).c_str());
|
||||
}
|
||||
if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
|
||||
compiler.parameter("color_space", "linear");
|
||||
@@ -446,8 +530,7 @@ EnvironmentTextureNode::EnvironmentTextureNode()
|
||||
: ImageSlotTextureNode(node_type)
|
||||
{
|
||||
image_manager = NULL;
|
||||
slot = -1;
|
||||
is_float = -1;
|
||||
is_float = false;
|
||||
is_linear = false;
|
||||
builtin_data = NULL;
|
||||
animated = false;
|
||||
@@ -455,12 +538,8 @@ EnvironmentTextureNode::EnvironmentTextureNode()
|
||||
|
||||
EnvironmentTextureNode::~EnvironmentTextureNode()
|
||||
{
|
||||
if(image_manager) {
|
||||
image_manager->remove_image(filename.string(),
|
||||
builtin_data,
|
||||
interpolation,
|
||||
EXTENSION_REPEAT,
|
||||
use_alpha);
|
||||
if(image_manager && slots.size()) {
|
||||
image_manager->remove_image(slots[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,8 +547,8 @@ ShaderNode *EnvironmentTextureNode::clone() const
|
||||
{
|
||||
EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
|
||||
node->image_manager = NULL;
|
||||
node->slot = -1;
|
||||
node->is_float = -1;
|
||||
node->slots.clear();
|
||||
node->is_float = false;
|
||||
node->is_linear = false;
|
||||
return node;
|
||||
}
|
||||
@@ -494,26 +573,27 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
|
||||
ShaderOutput *alpha_out = output("Alpha");
|
||||
|
||||
image_manager = compiler.image_manager;
|
||||
if(slot == -1) {
|
||||
if(slots.size() == 0) {
|
||||
ImageMetaData metadata;
|
||||
slot = image_manager->add_image(filename.string(),
|
||||
builtin_data,
|
||||
animated,
|
||||
0,
|
||||
interpolation,
|
||||
EXTENSION_REPEAT,
|
||||
use_alpha,
|
||||
metadata);
|
||||
slots.push_back(image_manager->add_image(filename.string(),
|
||||
builtin_data,
|
||||
animated,
|
||||
0,
|
||||
0,
|
||||
interpolation,
|
||||
EXTENSION_REPEAT,
|
||||
use_alpha,
|
||||
metadata));
|
||||
is_float = metadata.is_float;
|
||||
is_linear = metadata.is_linear;
|
||||
}
|
||||
|
||||
if(slot != -1) {
|
||||
if(slots[0] != -1) {
|
||||
int srgb = (is_linear || color_space != NODE_COLOR_SPACE_COLOR)? 0: 1;
|
||||
int vector_offset = tex_mapping.compile_begin(compiler, vector_in);
|
||||
|
||||
compiler.add_node(NODE_TEX_ENVIRONMENT,
|
||||
slot,
|
||||
slots[0],
|
||||
compiler.encode_uchar4(
|
||||
vector_offset,
|
||||
compiler.stack_assign_if_linked(color_out),
|
||||
@@ -546,30 +626,32 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
|
||||
* of builtin images.
|
||||
*/
|
||||
image_manager = compiler.image_manager;
|
||||
if(is_float == -1) {
|
||||
if(slots.size() == 0) {
|
||||
slots.resize(1);
|
||||
ImageMetaData metadata;
|
||||
if(builtin_data == NULL) {
|
||||
image_manager->get_image_metadata(filename.string(), NULL, metadata);
|
||||
}
|
||||
else {
|
||||
slot = image_manager->add_image(filename.string(),
|
||||
builtin_data,
|
||||
animated,
|
||||
0,
|
||||
interpolation,
|
||||
EXTENSION_REPEAT,
|
||||
use_alpha,
|
||||
metadata);
|
||||
slots[0] = image_manager->add_image(filename.string(),
|
||||
builtin_data,
|
||||
animated,
|
||||
0,
|
||||
0,
|
||||
interpolation,
|
||||
EXTENSION_REPEAT,
|
||||
use_alpha,
|
||||
metadata);
|
||||
}
|
||||
is_float = metadata.is_float;
|
||||
is_linear = metadata.is_linear;
|
||||
}
|
||||
|
||||
if(slot == -1) {
|
||||
if(slots[0] == -1) {
|
||||
compiler.parameter(this, "filename");
|
||||
}
|
||||
else {
|
||||
compiler.parameter("filename", string_printf("@i%d", slot).c_str());
|
||||
compiler.parameter("filename", string_printf("@i%d", slots[0]).c_str());
|
||||
}
|
||||
compiler.parameter(this, "projection");
|
||||
if(is_linear || color_space != NODE_COLOR_SPACE_COLOR)
|
||||
@@ -1495,11 +1577,7 @@ PointDensityTextureNode::PointDensityTextureNode()
|
||||
PointDensityTextureNode::~PointDensityTextureNode()
|
||||
{
|
||||
if(image_manager) {
|
||||
image_manager->remove_image(filename.string(),
|
||||
builtin_data,
|
||||
interpolation,
|
||||
EXTENSION_CLIP,
|
||||
true);
|
||||
image_manager->remove_image(slot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1525,7 +1603,7 @@ void PointDensityTextureNode::add_image()
|
||||
if(slot == -1) {
|
||||
ImageMetaData metadata;
|
||||
slot = image_manager->add_image(filename.string(), builtin_data,
|
||||
false, 0,
|
||||
false, 0, 0,
|
||||
interpolation,
|
||||
EXTENSION_CLIP,
|
||||
true,
|
||||
@@ -2055,7 +2133,7 @@ GlossyBsdfNode::GlossyBsdfNode()
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void GlossyBsdfNode::simplify_settings(Scene *scene)
|
||||
void GlossyBsdfNode::simplify_settings(Scene *scene, Shader * /*shader*/)
|
||||
{
|
||||
if(distribution_orig == NBUILTIN_CLOSURES) {
|
||||
roughness_orig = roughness;
|
||||
@@ -2150,7 +2228,7 @@ GlassBsdfNode::GlassBsdfNode()
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void GlassBsdfNode::simplify_settings(Scene *scene)
|
||||
void GlassBsdfNode::simplify_settings(Scene *scene, Shader * /*shader*/)
|
||||
{
|
||||
if(distribution_orig == NBUILTIN_CLOSURES) {
|
||||
roughness_orig = roughness;
|
||||
@@ -2245,7 +2323,7 @@ RefractionBsdfNode::RefractionBsdfNode()
|
||||
distribution_orig = NBUILTIN_CLOSURES;
|
||||
}
|
||||
|
||||
void RefractionBsdfNode::simplify_settings(Scene *scene)
|
||||
void RefractionBsdfNode::simplify_settings(Scene *scene, Shader * /*shader*/)
|
||||
{
|
||||
if(distribution_orig == NBUILTIN_CLOSURES) {
|
||||
roughness_orig = roughness;
|
||||
|
@@ -74,7 +74,7 @@ public:
|
||||
explicit ImageSlotTextureNode(const NodeType *node_type) : TextureNode(node_type) {
|
||||
special_type = SHADER_SPECIAL_TYPE_IMAGE_SLOT;
|
||||
}
|
||||
int slot;
|
||||
vector<int> slots;
|
||||
};
|
||||
|
||||
class ImageTextureNode : public ImageSlotTextureNode {
|
||||
@@ -84,9 +84,10 @@ public:
|
||||
ShaderNode *clone() const;
|
||||
void attributes(Shader *shader, AttributeRequestSet *attributes);
|
||||
bool has_attribute_dependency() { return true; }
|
||||
void simplify_settings(Scene *scene, Shader *shader);
|
||||
|
||||
ImageManager *image_manager;
|
||||
int is_float;
|
||||
bool is_float;
|
||||
bool is_linear;
|
||||
bool use_alpha;
|
||||
ustring filename;
|
||||
@@ -98,6 +99,7 @@ public:
|
||||
float projection_blend;
|
||||
bool animated;
|
||||
float3 vector;
|
||||
ccl::vector<int> tiles;
|
||||
|
||||
virtual bool equals(const ShaderNode& other)
|
||||
{
|
||||
@@ -118,7 +120,7 @@ public:
|
||||
virtual int get_group() { return NODE_GROUP_LEVEL_2; }
|
||||
|
||||
ImageManager *image_manager;
|
||||
int is_float;
|
||||
bool is_float;
|
||||
bool is_linear;
|
||||
bool use_alpha;
|
||||
ustring filename;
|
||||
@@ -450,7 +452,7 @@ class GlossyBsdfNode : public BsdfNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(GlossyBsdfNode)
|
||||
|
||||
void simplify_settings(Scene *scene);
|
||||
void simplify_settings(Scene *scene, Shader *shader);
|
||||
bool has_integrator_dependency();
|
||||
ClosureType get_closure_type() { return distribution; }
|
||||
|
||||
@@ -462,7 +464,7 @@ class GlassBsdfNode : public BsdfNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(GlassBsdfNode)
|
||||
|
||||
void simplify_settings(Scene *scene);
|
||||
void simplify_settings(Scene *scene, Shader *shader);
|
||||
bool has_integrator_dependency();
|
||||
ClosureType get_closure_type() { return distribution; }
|
||||
|
||||
@@ -474,7 +476,7 @@ class RefractionBsdfNode : public BsdfNode {
|
||||
public:
|
||||
SHADER_NODE_CLASS(RefractionBsdfNode)
|
||||
|
||||
void simplify_settings(Scene *scene);
|
||||
void simplify_settings(Scene *scene, Shader *shader);
|
||||
bool has_integrator_dependency();
|
||||
ClosureType get_closure_type() { return distribution; }
|
||||
|
||||
|
@@ -170,6 +170,8 @@ public:
|
||||
bool persistent_data;
|
||||
int texture_limit;
|
||||
|
||||
bool background;
|
||||
|
||||
SceneParams()
|
||||
{
|
||||
shadingsystem = SHADINGSYSTEM_SVM;
|
||||
|
@@ -579,7 +579,8 @@ void ShaderManager::add_default(Scene *scene)
|
||||
{
|
||||
/* default surface */
|
||||
{
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
Shader *shader = new Shader();
|
||||
ShaderGraph *graph = new ShaderGraph(shader);
|
||||
|
||||
DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
|
||||
diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
|
||||
@@ -587,7 +588,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
|
||||
graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
|
||||
|
||||
Shader *shader = new Shader();
|
||||
shader->name = "default_surface";
|
||||
shader->graph = graph;
|
||||
scene->shaders.push_back(shader);
|
||||
@@ -596,7 +596,8 @@ void ShaderManager::add_default(Scene *scene)
|
||||
|
||||
/* default light */
|
||||
{
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
Shader *shader = new Shader();
|
||||
ShaderGraph *graph = new ShaderGraph(shader);
|
||||
|
||||
EmissionNode *emission = new EmissionNode();
|
||||
emission->color = make_float3(0.8f, 0.8f, 0.8f);
|
||||
@@ -605,7 +606,6 @@ void ShaderManager::add_default(Scene *scene)
|
||||
|
||||
graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
|
||||
|
||||
Shader *shader = new Shader();
|
||||
shader->name = "default_light";
|
||||
shader->graph = graph;
|
||||
scene->shaders.push_back(shader);
|
||||
@@ -614,9 +614,9 @@ void ShaderManager::add_default(Scene *scene)
|
||||
|
||||
/* default background */
|
||||
{
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
Shader *shader = new Shader();
|
||||
ShaderGraph *graph = new ShaderGraph(shader);
|
||||
|
||||
shader->name = "default_background";
|
||||
shader->graph = graph;
|
||||
scene->shaders.push_back(shader);
|
||||
@@ -625,9 +625,9 @@ void ShaderManager::add_default(Scene *scene)
|
||||
|
||||
/* default empty */
|
||||
{
|
||||
ShaderGraph *graph = new ShaderGraph();
|
||||
|
||||
Shader *shader = new Shader();
|
||||
ShaderGraph *graph = new ShaderGraph(shader);
|
||||
|
||||
shader->name = "default_empty";
|
||||
shader->graph = graph;
|
||||
scene->shaders.push_back(shader);
|
||||
|
@@ -736,6 +736,10 @@ class IMAGE_PT_view_properties(Panel):
|
||||
row.active = uvedit.show_other_objects
|
||||
row.prop(uvedit, "other_uv_filter", text="Filter")
|
||||
|
||||
if ima is None:
|
||||
row = layout.row()
|
||||
row.prop(uvedit, "tile_grid_shape", text="Grid Shape")
|
||||
|
||||
|
||||
class IMAGE_UL_render_slots(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
|
||||
@@ -773,6 +777,33 @@ class IMAGE_PT_render_slots(Panel):
|
||||
col.operator("image.clear_render_slot", icon='X', text="")
|
||||
|
||||
|
||||
class IMAGE_PT_tile_properties(Panel):
|
||||
bl_space_type = 'IMAGE_EDITOR'
|
||||
bl_region_type = 'UI'
|
||||
bl_label = "Tiles"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
sima = context.space_data
|
||||
return (sima and sima.image and sima.image.source == 'TILED')
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
sima = context.space_data
|
||||
ima = sima.image
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("image.add_tile")
|
||||
row.operator("image.remove_tile")
|
||||
|
||||
tile = ima.tiles.get(sima.current_tile)
|
||||
if tile:
|
||||
col = layout.column(align=True)
|
||||
col.operator("image.fill_tile")
|
||||
col.prop(tile, "label")
|
||||
|
||||
|
||||
class IMAGE_PT_tools_transform_uvs(Panel, UVToolsPanel):
|
||||
bl_label = "Transform"
|
||||
|
||||
@@ -1407,6 +1438,7 @@ classes = (
|
||||
IMAGE_UL_render_slots,
|
||||
IMAGE_PT_render_slots,
|
||||
IMAGE_PT_view_properties,
|
||||
IMAGE_PT_tile_properties,
|
||||
IMAGE_PT_tools_transform_uvs,
|
||||
IMAGE_PT_tools_align_uvs,
|
||||
IMAGE_PT_tools_uvs,
|
||||
|
@@ -74,6 +74,7 @@ void BLF_size(int fontid, int size, int dpi);
|
||||
void BLF_color4ubv(int fontid, const unsigned char rgba[4]);
|
||||
void BLF_color3ubv(int fontid, const unsigned char rgb[3]);
|
||||
void BLF_color3ubv_alpha(int fontid, const unsigned char rgb[3], unsigned char alpha);
|
||||
void BLF_color4ub(int fontid, unsigned char r, unsigned char g, unsigned char b, unsigned char alpha);
|
||||
void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b);
|
||||
void BLF_color4f(int fontid, float r, float g, float b, float a);
|
||||
void BLF_color4fv(int fontid, const float rgba[4]);
|
||||
|
@@ -513,6 +513,18 @@ void BLF_color3ub(int fontid, unsigned char r, unsigned char g, unsigned char b)
|
||||
}
|
||||
}
|
||||
|
||||
void BLF_color4ub(int fontid, unsigned char r, unsigned char g, unsigned char b, unsigned char alpha)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
||||
if (font) {
|
||||
font->color[0] = r;
|
||||
font->color[1] = g;
|
||||
font->color[2] = b;
|
||||
font->color[3] = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
void BLF_color4fv(int fontid, const float rgba[4])
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
|
@@ -45,6 +45,7 @@ struct Scene;
|
||||
struct Object;
|
||||
struct ImageFormatData;
|
||||
struct ImagePool;
|
||||
struct ImageTile;
|
||||
struct Main;
|
||||
struct ReportList;
|
||||
struct RenderResult;
|
||||
@@ -134,6 +135,7 @@ struct RenderResult;
|
||||
#define IMA_SRC_MOVIE 3
|
||||
#define IMA_SRC_GENERATED 4
|
||||
#define IMA_SRC_VIEWER 5
|
||||
#define IMA_SRC_TILED 6
|
||||
|
||||
/* ima->type, how to handle/generate it */
|
||||
#define IMA_TYPE_IMAGE 0
|
||||
@@ -194,7 +196,7 @@ struct Image *BKE_image_load_exists(struct Main *bmain, const char *filepath);
|
||||
/* adds image, adds ibuf, generates color or pattern */
|
||||
struct Image *BKE_image_add_generated(
|
||||
struct Main *bmain, unsigned int width, unsigned int height, const char *name,
|
||||
int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d);
|
||||
int depth, int floatbuf, short gen_type, const float color[4], const bool stereo3d, bool tiled);
|
||||
/* adds image from imbuf, owns imbuf */
|
||||
struct Image *BKE_image_add_from_imbuf(struct Main *bmain, struct ImBuf *ibuf, const char *name);
|
||||
|
||||
@@ -271,6 +273,19 @@ bool BKE_image_has_alpha(struct Image *image);
|
||||
/* check if texture has gpu texture code */
|
||||
bool BKE_image_has_opengl_texture(struct Image *ima);
|
||||
|
||||
/* get tile index for tiled images */
|
||||
void BKE_image_get_tile_label(struct Image *ima, struct ImageTile *tile, char *label, int len_label);
|
||||
|
||||
struct ImageTile *BKE_image_add_tile(struct Image *ima, int tile_number, const char *label);
|
||||
bool BKE_image_remove_tile(struct Image *ima, struct ImageTile *tile);
|
||||
|
||||
bool BKE_image_fill_tile(struct Image *ima, struct ImageTile *tile, int width, int height, const float color[4], int gen_type);
|
||||
|
||||
struct ImageTile *BKE_image_get_tile(struct Image *ima, int tile_number);
|
||||
struct ImageTile *BKE_image_get_tile_from_iuser(struct Image *ima, struct ImageUser *iuser);
|
||||
|
||||
int BKE_image_get_tile_from_pos(struct Image *ima, const float uv[2], float new_uv[2], float ofs[2]);
|
||||
|
||||
void BKE_image_get_size(struct Image *image, struct ImageUser *iuser, int *width, int *height);
|
||||
void BKE_image_get_size_fl(struct Image *image, struct ImageUser *iuser, float size[2]);
|
||||
void BKE_image_get_aspect(struct Image *image, float *aspx, float *aspy);
|
||||
@@ -281,14 +296,15 @@ void BKE_image_buf_fill_checker(unsigned char *rect, float *rect_float, int heig
|
||||
void BKE_image_buf_fill_checker_color(unsigned char *rect, float *rect_float, int height, int width);
|
||||
|
||||
/* Cycles hookup */
|
||||
unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame);
|
||||
float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame);
|
||||
unsigned char *BKE_image_get_pixels_for_frame(struct Image *image, int frame, int tile);
|
||||
float *BKE_image_get_float_pixels_for_frame(struct Image *image, int frame, int tile);
|
||||
|
||||
/* Guess offset for the first frame in the sequence */
|
||||
int BKE_image_sequence_guess_offset(struct Image *image);
|
||||
bool BKE_image_has_anim(struct Image *image);
|
||||
bool BKE_image_has_packedfile(struct Image *image);
|
||||
bool BKE_image_is_animated(struct Image *image);
|
||||
bool BKE_image_has_multiple_ibufs(struct Image *image);
|
||||
bool BKE_image_is_dirty(struct Image *image);
|
||||
void BKE_image_file_format_set(struct Image *image, int ftype, const struct ImbFormatOptions *options);
|
||||
bool BKE_image_has_loaded_ibuf(struct Image *image);
|
||||
|
@@ -435,7 +435,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int
|
||||
Image *ima;
|
||||
ima = (Image *)id;
|
||||
if (BKE_image_has_packedfile(ima) == false || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) {
|
||||
if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
|
||||
if (ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
|
||||
if (rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data)) {
|
||||
if (flag & BKE_BPATH_TRAVERSE_RELOAD_EDITED) {
|
||||
if (!BKE_image_has_packedfile(ima) &&
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -237,7 +237,7 @@ void packAll(Main *bmain, ReportList *reports, bool verbose)
|
||||
BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id));
|
||||
tot ++;
|
||||
}
|
||||
else if (BKE_image_is_animated(ima) && verbose) {
|
||||
else if (BKE_image_has_multiple_ibufs(ima) && verbose) {
|
||||
BKE_reportf(reports, RPT_WARNING, "Image '%s' skipped, movies and image sequences not supported",
|
||||
ima->id.name + 2);
|
||||
}
|
||||
|
@@ -262,6 +262,8 @@ MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED
|
||||
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
|
||||
MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
MINLINE bool equals_v2v2_int(const int v1[2], const int v2[2]) ATTR_WARN_UNUSED_RESULT;
|
||||
|
||||
MINLINE bool compare_v2v2(const float a[2], const float b[2], const float limit) ATTR_WARN_UNUSED_RESULT;
|
||||
MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT;
|
||||
MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT;
|
||||
|
@@ -1042,6 +1042,11 @@ MINLINE bool equals_v4v4(const float v1[4], const float v2[4])
|
||||
return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3]));
|
||||
}
|
||||
|
||||
MINLINE bool equals_v2v2_int(const int v1[2], const int v2[2])
|
||||
{
|
||||
return ((v1[0] == v2[0]) && (v1[1] == v2[1]));
|
||||
}
|
||||
|
||||
MINLINE bool compare_v2v2(const float v1[2], const float v2[2], const float limit)
|
||||
{
|
||||
return (compare_ff(v1[0], v2[0], limit) &&
|
||||
|
@@ -1677,21 +1677,24 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain)
|
||||
{
|
||||
Image *ima = oldmain->image.first;
|
||||
Scene *sce = oldmain->scene.first;
|
||||
int a;
|
||||
|
||||
fd->imamap = oldnewmap_new();
|
||||
|
||||
for (; ima; ima = ima->id.next) {
|
||||
if (ima->cache)
|
||||
oldnewmap_insert(fd->imamap, ima->cache, ima->cache, 0);
|
||||
for (a = 0; a < TEXTARGET_COUNT; a++)
|
||||
if (ima->gputexture[a])
|
||||
oldnewmap_insert(fd->imamap, ima->gputexture[a], ima->gputexture[a], 0);
|
||||
if (ima->rr)
|
||||
oldnewmap_insert(fd->imamap, ima->rr, ima->rr, 0);
|
||||
LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots)
|
||||
if (slot->render)
|
||||
oldnewmap_insert(fd->imamap, slot->render, slot->render, 0);
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
for (int a = 0; a < TEXTARGET_COUNT; a++) {
|
||||
if (tile->gputexture[a]) {
|
||||
oldnewmap_insert(fd->imamap, tile->gputexture[a], tile->gputexture[a], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots)
|
||||
if (slot->render)
|
||||
oldnewmap_insert(fd->imamap, slot->render, slot->render, 0);
|
||||
}
|
||||
for (; sce; sce = sce->id.next) {
|
||||
if (sce->nodetree && sce->nodetree->previews) {
|
||||
@@ -1711,10 +1714,9 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
|
||||
OldNew *entry = fd->imamap->entries;
|
||||
Image *ima = oldmain->image.first;
|
||||
Scene *sce = oldmain->scene.first;
|
||||
int i;
|
||||
|
||||
/* used entries were restored, so we put them to zero */
|
||||
for (i = 0; i < fd->imamap->nentries; i++, entry++) {
|
||||
for (int i = 0; i < fd->imamap->nentries; i++, entry++) {
|
||||
if (entry->nr > 0)
|
||||
entry->newp = NULL;
|
||||
}
|
||||
@@ -1723,16 +1725,23 @@ void blo_end_image_pointer_map(FileData *fd, Main *oldmain)
|
||||
ima->cache = newimaadr(fd, ima->cache);
|
||||
if (ima->cache == NULL) {
|
||||
ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
|
||||
for (i = 0; i < TEXTARGET_COUNT; i++) {
|
||||
ima->gputexture[i] = NULL;
|
||||
}
|
||||
ima->rr = NULL;
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
for (int j = 0; j < TEXTARGET_COUNT; j++) {
|
||||
tile->gputexture[j] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH(RenderSlot *, slot, &ima->renderslots)
|
||||
slot->render = newimaadr(fd, slot->render);
|
||||
|
||||
for (i = 0; i < TEXTARGET_COUNT; i++)
|
||||
ima->gputexture[i] = newimaadr(fd, ima->gputexture[i]);
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
for (int j = 0; j < TEXTARGET_COUNT; j++) {
|
||||
tile->gputexture[j] = newimaadr(fd, tile->gputexture[j]);
|
||||
}
|
||||
}
|
||||
|
||||
ima->rr = newimaadr(fd, ima->rr);
|
||||
}
|
||||
for (; sce; sce = sce->id.next) {
|
||||
@@ -3950,11 +3959,15 @@ static void direct_link_image(FileData *fd, Image *ima)
|
||||
else
|
||||
ima->cache = NULL;
|
||||
|
||||
link_list(fd, &(ima->tiles));
|
||||
|
||||
/* if not restored, we keep the binded opengl index */
|
||||
if (!ima->cache) {
|
||||
ima->tpageflag &= ~IMA_GLBIND_IS_DATA;
|
||||
for (int i = 0; i < TEXTARGET_COUNT; i++) {
|
||||
ima->gputexture[i] = NULL;
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
for (int i = 0; i < TEXTARGET_COUNT; i++) {
|
||||
tile->gputexture[i] = NULL;
|
||||
}
|
||||
}
|
||||
ima->rr = NULL;
|
||||
}
|
||||
@@ -3989,7 +4002,10 @@ static void direct_link_image(FileData *fd, Image *ima)
|
||||
BLI_listbase_clear(&ima->anims);
|
||||
ima->preview = direct_link_preview_image(fd, ima->preview);
|
||||
ima->stereo3d_format = newdataadr(fd, ima->stereo3d_format);
|
||||
ima->ok = 1;
|
||||
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
tile->ok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1490,6 +1490,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "SpaceAction", "char", "mode_prev")) {
|
||||
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
|
||||
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
|
||||
@@ -1640,6 +1641,28 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
||||
BKE_screen_view3d_shading_init(&scene->display.shading);
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "Image", "short", "num_tiles")) {
|
||||
for (Image *ima = bmain->image.first; ima; ima = ima->id.next) {
|
||||
ImageTile *tile = MEM_callocN(sizeof(ImageTile), "Image Tiles");
|
||||
tile->ok = 1;
|
||||
BLI_addtail(&ima->tiles, tile);
|
||||
}
|
||||
}
|
||||
|
||||
if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "int", "tile_grid_shape[2]")) {
|
||||
for (bScreen *screen = bmain->screen.first; screen; screen = screen->id.next) {
|
||||
for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
|
||||
for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
|
||||
if (sl->spacetype == SPACE_IMAGE) {
|
||||
SpaceImage *sima = (SpaceImage *)sl;
|
||||
sima->tile_grid_shape[0] = 1;
|
||||
sima->tile_grid_shape[1] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2210,6 +2210,8 @@ static void write_image(WriteData *wd, Image *ima)
|
||||
}
|
||||
writestruct(wd, DATA, Stereo3dFormat, 1, ima->stereo3d_format);
|
||||
|
||||
writelist(wd, DATA, ImageTile, &ima->tiles);
|
||||
|
||||
ima->packedfile = NULL;
|
||||
|
||||
writelist(wd, DATA, RenderSlot, &ima->renderslots);
|
||||
|
@@ -155,7 +155,8 @@ void ViewerOperation::initImage()
|
||||
/* zero size can happen if no image buffers exist to define a sensible resolution */
|
||||
if (ibuf->x > 0 && ibuf->y > 0)
|
||||
imb_addrectfloatImBuf(ibuf);
|
||||
ima->ok = IMA_OK_LOADED;
|
||||
ImageTile *tile = BKE_image_get_tile(ima, 0);
|
||||
tile->ok = IMA_OK_LOADED;
|
||||
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
}
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_rand.h"
|
||||
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_particle.h"
|
||||
@@ -568,7 +569,7 @@ void workbench_deferred_cache_init(WORKBENCH_Data *vedata)
|
||||
}
|
||||
|
||||
static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int color_type)
|
||||
WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int color_type, int image_tile)
|
||||
{
|
||||
WORKBENCH_StorageList *stl = vedata->stl;
|
||||
WORKBENCH_PassList *psl = vedata->psl;
|
||||
@@ -583,6 +584,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
|
||||
material_template.color_type = color_type;
|
||||
material_template.ima = ima;
|
||||
material_template.image_tile = image_tile;
|
||||
uint hash = workbench_material_get_hash(&material_template);
|
||||
|
||||
material = BLI_ghash_lookup(wpd->material_hash, SET_UINT_IN_POINTER(hash));
|
||||
@@ -628,7 +630,7 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
|
||||
Material *mat = give_current_material(ob, part->omat);
|
||||
ED_object_get_active_image(ob, part->omat, &image, NULL, NULL, NULL);
|
||||
int color_type = workbench_material_determine_color_type(wpd, image);
|
||||
WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, mat, image, color_type);
|
||||
WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, mat, image, color_type, 0);
|
||||
|
||||
struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ?
|
||||
wpd->prepass_solid_hair_sh :
|
||||
@@ -680,23 +682,32 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
||||
bool is_drawn = false;
|
||||
if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) {
|
||||
const Mesh *me = ob->data;
|
||||
if (me->mloopuv) {
|
||||
if (me->mloopuv && me->totcol) {
|
||||
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
|
||||
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
|
||||
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
|
||||
if (materials_len > 0 && geom_array) {
|
||||
for (int i = 0; i < materials_len; i++) {
|
||||
if (geom_array[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Material *mat = give_current_material(ob, i + 1);
|
||||
Image *image;
|
||||
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
|
||||
int color_type = workbench_material_determine_color_type(wpd, image);
|
||||
material = get_or_create_material_data(vedata, ob, mat, image, color_type);
|
||||
DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
|
||||
bool *is_tiled = MEM_mallocN(sizeof(bool)*materials_len, "workbench deferred is tiled");
|
||||
for(int i = 0; i < materials_len; i++) {
|
||||
Image *image;
|
||||
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
|
||||
is_tiled[i] = image && (image->source == IMA_SRC_TILED);
|
||||
}
|
||||
|
||||
int num_batches = 0;
|
||||
struct TexpaintCacheBatch *geom_batches = DRW_cache_mesh_surface_texpaint_get(ob, is_tiled, &num_batches);
|
||||
|
||||
for (int i = 0; i < num_batches; i++) {
|
||||
if (geom_batches[i].batch == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int matid = geom_batches[i].material + 1;
|
||||
Material *mat = give_current_material(ob, matid);
|
||||
Image *image;
|
||||
ED_object_get_active_image(ob, matid, &image, NULL, NULL, NULL);
|
||||
int color_type = workbench_material_determine_color_type(wpd, image);
|
||||
material = get_or_create_material_data(vedata, ob, mat, image, color_type, geom_batches[i].tile);
|
||||
DRW_shgroup_call_object_add(material->shgrp, geom_batches[i].batch, ob);
|
||||
|
||||
is_drawn = true;
|
||||
}
|
||||
}
|
||||
@@ -708,7 +719,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
||||
/* No material split needed */
|
||||
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
|
||||
if (geom) {
|
||||
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type);
|
||||
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type, 0);
|
||||
if (is_sculpt_mode) {
|
||||
DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
|
||||
}
|
||||
@@ -733,7 +744,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
||||
}
|
||||
|
||||
Material *mat = give_current_material(ob, i + 1);
|
||||
material = get_or_create_material_data(vedata, ob, mat, NULL, V3D_SHADING_MATERIAL_COLOR);
|
||||
material = get_or_create_material_data(vedata, ob, mat, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
|
||||
if (is_sculpt_mode) {
|
||||
DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "BLI_dynstr.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_particle.h"
|
||||
#include "BKE_modifier.h"
|
||||
@@ -137,7 +138,7 @@ static void workbench_init_object_data(DrawData *dd)
|
||||
}
|
||||
|
||||
static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int color_type)
|
||||
WORKBENCH_Data *vedata, Object *ob, Material *mat, Image *ima, int color_type, int image_tile)
|
||||
{
|
||||
WORKBENCH_StorageList *stl = vedata->stl;
|
||||
WORKBENCH_PassList *psl = vedata->psl;
|
||||
@@ -153,6 +154,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
material_template.object_id = OBJECT_ID_PASS_ENABLED(wpd) ? engine_object_data->object_id : 1;
|
||||
material_template.color_type = color_type;
|
||||
material_template.ima = ima;
|
||||
material_template.image_tile = image_tile;
|
||||
uint hash = workbench_material_get_hash(&material_template);
|
||||
|
||||
material = BLI_ghash_lookup(wpd->material_hash, SET_UINT_IN_POINTER(hash));
|
||||
@@ -181,9 +183,12 @@ static WORKBENCH_MaterialData *get_or_create_material_data(
|
||||
|
||||
/* Depth */
|
||||
if (workbench_material_determine_color_type(wpd, material->ima) == V3D_SHADING_TEXTURE_COLOR) {
|
||||
ImageUser iuser = {NULL};
|
||||
iuser.ok = 1;
|
||||
iuser.tile = material->image_tile;
|
||||
material->shgrp_object_outline = DRW_shgroup_create(
|
||||
e_data.object_outline_texture_sh, psl->object_outline_pass);
|
||||
GPUTexture *tex = GPU_texture_from_blender(material->ima, NULL, GL_TEXTURE_2D, false, 0.0f);
|
||||
GPUTexture *tex = GPU_texture_from_blender(material->ima, &iuser, GL_TEXTURE_2D, false, 0.0f);
|
||||
DRW_shgroup_uniform_texture(material->shgrp_object_outline, "image", tex);
|
||||
}
|
||||
else {
|
||||
@@ -420,7 +425,7 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
|
||||
Material *mat = give_current_material(ob, part->omat);
|
||||
ED_object_get_active_image(ob, part->omat, &image, NULL, NULL, NULL);
|
||||
int color_type = workbench_material_determine_color_type(wpd, image);
|
||||
WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, mat, image, color_type);
|
||||
WORKBENCH_MaterialData *material = get_or_create_material_data(vedata, ob, mat, image, color_type, 0);
|
||||
|
||||
struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR)
|
||||
? wpd->transparent_accum_hair_sh
|
||||
@@ -490,31 +495,39 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
||||
const Mesh *me = ob->data;
|
||||
if (me->mloopuv) {
|
||||
const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
|
||||
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
|
||||
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
|
||||
if (materials_len > 0 && geom_array) {
|
||||
for (int i = 0; i < materials_len; i++) {
|
||||
if (geom_array[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Material *mat = give_current_material(ob, i + 1);
|
||||
Image *image;
|
||||
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
|
||||
/* use OB_SOLID when no texture could be determined */
|
||||
bool *is_tiled = MEM_mallocN(sizeof(bool)*materials_len, "workbench forward is tiled");
|
||||
for(int i = 0; i < materials_len; i++) {
|
||||
Image *image;
|
||||
ED_object_get_active_image(ob, i + 1, &image, NULL, NULL, NULL);
|
||||
is_tiled[i] = image && (image->source == IMA_SRC_TILED);
|
||||
}
|
||||
|
||||
int color_type = wpd->shading.color_type;
|
||||
if (color_type == V3D_SHADING_TEXTURE_COLOR) {
|
||||
/* use OB_SOLID when no texture could be determined */
|
||||
if (image == NULL) {
|
||||
color_type = V3D_SHADING_MATERIAL_COLOR;
|
||||
}
|
||||
}
|
||||
int num_batches = 0;
|
||||
struct TexpaintCacheBatch *geom_batches = DRW_cache_mesh_surface_texpaint_get(ob, is_tiled, &num_batches);
|
||||
|
||||
material = get_or_create_material_data(vedata, ob, mat, image, color_type);
|
||||
DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob);
|
||||
DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
|
||||
for (int i = 0; i < num_batches; i++) {
|
||||
if (geom_batches[i].batch == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int matid = geom_batches[i].material + 1;
|
||||
Material *mat = give_current_material(ob, matid);
|
||||
Image *image;
|
||||
ED_object_get_active_image(ob, matid, &image, NULL, NULL, NULL);
|
||||
/* use OB_SOLID when no texture could be determined */
|
||||
|
||||
int color_type = wpd->shading.color_type;
|
||||
if (color_type == V3D_SHADING_TEXTURE_COLOR) {
|
||||
/* use OB_SOLID when no texture could be determined */
|
||||
if (image == NULL) {
|
||||
color_type = V3D_SHADING_MATERIAL_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
material = get_or_create_material_data(vedata, ob, mat, image, color_type, geom_batches[i].tile);
|
||||
DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_batches[i].batch, ob);
|
||||
DRW_shgroup_call_object_add(material->shgrp, geom_batches[i].batch, ob);
|
||||
is_drawn = true;
|
||||
}
|
||||
}
|
||||
@@ -526,7 +539,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
||||
/* No material split needed */
|
||||
struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
|
||||
if (geom) {
|
||||
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type);
|
||||
material = get_or_create_material_data(vedata, ob, NULL, NULL, wpd->shading.color_type, 0);
|
||||
if (is_sculpt_mode) {
|
||||
DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
|
||||
DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
|
||||
@@ -553,7 +566,7 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
|
||||
}
|
||||
|
||||
Material *mat = give_current_material(ob, i + 1);
|
||||
material = get_or_create_material_data(vedata, ob, mat, NULL, V3D_SHADING_MATERIAL_COLOR);
|
||||
material = get_or_create_material_data(vedata, ob, mat, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
|
||||
if (is_sculpt_mode) {
|
||||
DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
|
||||
DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
|
||||
|
@@ -131,6 +131,7 @@ uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template)
|
||||
/* add texture reference */
|
||||
if (material_template->ima) {
|
||||
result += BLI_ghashutil_inthash_p_murmur(material_template->ima);
|
||||
result += BLI_ghashutil_inthash(material_template->image_tile);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -185,7 +186,10 @@ void workbench_material_shgroup_uniform(
|
||||
WORKBENCH_PrivateData *wpd, DRWShadingGroup *grp, WORKBENCH_MaterialData *material)
|
||||
{
|
||||
if (workbench_material_determine_color_type(wpd, material->ima) == V3D_SHADING_TEXTURE_COLOR) {
|
||||
GPUTexture *tex = GPU_texture_from_blender(material->ima, NULL, GL_TEXTURE_2D, false, 0.0f);
|
||||
ImageUser iuser = {NULL};
|
||||
iuser.ok = 1;
|
||||
iuser.tile = material->image_tile;
|
||||
GPUTexture *tex = GPU_texture_from_blender(material->ima, &iuser, GL_TEXTURE_2D, false, 0.0f);
|
||||
DRW_shgroup_uniform_texture(grp, "image", tex);
|
||||
}
|
||||
else {
|
||||
@@ -205,4 +209,5 @@ void workbench_material_copy(WORKBENCH_MaterialData *dest_material, const WORKBE
|
||||
copy_v4_v4(dest_material->specular_color, source_material->specular_color);
|
||||
dest_material->roughness = source_material->roughness;
|
||||
dest_material->ima = source_material->ima;
|
||||
dest_material->image_tile = source_material->image_tile;
|
||||
}
|
||||
|
@@ -205,6 +205,7 @@ typedef struct WORKBENCH_MaterialData {
|
||||
int object_id;
|
||||
int color_type;
|
||||
Image *ima;
|
||||
int image_tile;
|
||||
|
||||
/* Linked shgroup for drawing */
|
||||
DRWShadingGroup *shgrp;
|
||||
|
@@ -2870,20 +2870,20 @@ GPUBatch **DRW_cache_mesh_surface_shaded_get(
|
||||
}
|
||||
|
||||
/* Return list of batches */
|
||||
GPUBatch **DRW_cache_mesh_surface_texpaint_get(Object *ob)
|
||||
TexpaintCacheBatch *DRW_cache_mesh_surface_texpaint_get(Object *ob, bool *is_tiled, int *num_batches)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
|
||||
Mesh *me = ob->data;
|
||||
return DRW_mesh_batch_cache_get_surface_texpaint(me);
|
||||
return DRW_mesh_batch_cache_get_surface_texpaint(me, is_tiled, num_batches);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob)
|
||||
TexpaintCacheBatch *DRW_cache_mesh_surface_texpaint_single_get(Object *ob, bool is_tiled, int *num_batches)
|
||||
{
|
||||
BLI_assert(ob->type == OB_MESH);
|
||||
|
||||
Mesh *me = ob->data;
|
||||
return DRW_mesh_batch_cache_get_surface_texpaint_single(me);
|
||||
return DRW_mesh_batch_cache_get_surface_texpaint_single(me, is_tiled, num_batches);
|
||||
}
|
||||
|
||||
GPUBatch *DRW_cache_mesh_surface_verts_get(Object *ob)
|
||||
|
@@ -32,6 +32,12 @@ struct ModifierData;
|
||||
struct Object;
|
||||
struct PTCacheEdit;
|
||||
|
||||
typedef struct TexpaintCacheBatch {
|
||||
struct GPUBatch *batch;
|
||||
int material;
|
||||
int tile;
|
||||
} TexpaintCacheBatch;
|
||||
|
||||
void DRW_shape_cache_free(void);
|
||||
void DRW_shape_cache_reset(void);
|
||||
|
||||
@@ -142,8 +148,8 @@ struct GPUBatch *DRW_cache_mesh_verts_weight_overlay_get(struct Object *ob);
|
||||
struct GPUBatch **DRW_cache_mesh_surface_shaded_get(
|
||||
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
|
||||
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
|
||||
struct GPUBatch **DRW_cache_mesh_surface_texpaint_get(struct Object *ob);
|
||||
struct GPUBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob);
|
||||
struct TexpaintCacheBatch *DRW_cache_mesh_surface_texpaint_get(struct Object *ob, bool *is_tiled, int *num_batches);
|
||||
struct TexpaintCacheBatch *DRW_cache_mesh_surface_texpaint_single_get(struct Object *ob, bool is_tiled, int *num_batches);
|
||||
|
||||
void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);
|
||||
|
||||
|
@@ -97,8 +97,8 @@ struct GPUBatch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt);
|
||||
struct GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
|
||||
struct Mesh *me, struct GPUMaterial **gpumat_array, uint gpumat_array_len,
|
||||
char **auto_layer_names, int **auto_layer_is_srgb, int *auto_layer_count);
|
||||
struct GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me);
|
||||
struct TexpaintCacheBatch *DRW_mesh_batch_cache_get_surface_texpaint(struct Mesh *me, bool *is_tiled, int *num_batches);
|
||||
struct TexpaintCacheBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(struct Mesh *me, bool is_tiled, int *num_batches);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_edges(struct Mesh *me, bool use_wire, bool use_sel);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_faces(struct Mesh *me);
|
||||
struct GPUBatch *DRW_mesh_batch_cache_get_weight_overlay_verts(struct Mesh *me);
|
||||
|
@@ -1558,6 +1558,8 @@ typedef struct MeshBatchCache {
|
||||
GPUVertBuf *pos_with_normals;
|
||||
GPUVertBuf *tri_aligned_uv; /* Active UV layer (mloopuv) */
|
||||
|
||||
int *tri_tiles;
|
||||
|
||||
/**
|
||||
* Other uses are all positions or loose elements.
|
||||
* This stores all visible elements, needed for selection.
|
||||
@@ -1599,12 +1601,16 @@ typedef struct MeshBatchCache {
|
||||
GPUVertFormat shaded_triangles_format;
|
||||
GPUVertBuf *shaded_triangles_data;
|
||||
GPUIndexBuf **shaded_triangles_in_order;
|
||||
GPUIndexBuf **shaded_triangles_in_order_tiled;
|
||||
GPUIndexBuf **shaded_triangles_in_order_tiled_single;
|
||||
GPUBatch **shaded_triangles;
|
||||
|
||||
/* Texture Paint.*/
|
||||
/* per-texture batch */
|
||||
GPUBatch **texpaint_triangles;
|
||||
GPUBatch *texpaint_triangles_single;
|
||||
int num_texpaint_batches;
|
||||
int num_texpaint_batches_single;
|
||||
TexpaintCacheBatch *texpaint_triangles;
|
||||
TexpaintCacheBatch *texpaint_triangles_single;
|
||||
|
||||
/* Edit Cage Mesh buffers */
|
||||
GPUVertBuf *ed_tri_pos;
|
||||
@@ -1801,12 +1807,17 @@ static void mesh_batch_cache_clear_selective(Mesh *me, GPUVertBuf *vert)
|
||||
}
|
||||
MEM_SAFE_FREE(cache->shaded_triangles);
|
||||
if (cache->texpaint_triangles) {
|
||||
for (int i = 0; i < cache->mat_len; ++i) {
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
|
||||
for (int i = 0; i < cache->num_texpaint_batches; ++i) {
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i].batch);
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(cache->texpaint_triangles);
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
|
||||
if (cache->texpaint_triangles_single) {
|
||||
for (int i = 0; i < cache->num_texpaint_batches_single; ++i) {
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single[i].batch);
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(cache->texpaint_triangles_single);
|
||||
}
|
||||
/* TODO: add the other ones if needed. */
|
||||
else {
|
||||
@@ -1859,6 +1870,7 @@ static void mesh_batch_cache_clear(Mesh *me)
|
||||
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_weights);
|
||||
GPU_BATCH_DISCARD_SAFE(cache->triangles_with_vert_colors);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->tri_aligned_uv);
|
||||
MEM_SAFE_FREE(cache->tri_tiles);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->ed_fcenter_pos_with_nor_and_sel);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->ed_edge_pos);
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->ed_vert_pos);
|
||||
@@ -1877,31 +1889,50 @@ static void mesh_batch_cache_clear(Mesh *me)
|
||||
DRW_TEXTURE_FREE_SAFE(cache->edges_face_overlay_tx);
|
||||
|
||||
GPU_VERTBUF_DISCARD_SAFE(cache->shaded_triangles_data);
|
||||
|
||||
if (cache->shaded_triangles_in_order) {
|
||||
for (int i = 0; i < cache->mat_len; ++i) {
|
||||
GPU_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order[i]);
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(cache->shaded_triangles_in_order);
|
||||
|
||||
if (cache->shaded_triangles_in_order_tiled) {
|
||||
for (int i = 0; i < cache->num_texpaint_batches; ++i) {
|
||||
GPU_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order_tiled[i]);
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(cache->shaded_triangles_in_order_tiled);
|
||||
|
||||
if (cache->shaded_triangles_in_order_tiled_single) {
|
||||
for (int i = 0; i < cache->num_texpaint_batches_single; ++i) {
|
||||
GPU_INDEXBUF_DISCARD_SAFE(cache->shaded_triangles_in_order_tiled_single[i]);
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(cache->shaded_triangles_in_order_tiled_single);
|
||||
|
||||
if (cache->shaded_triangles) {
|
||||
for (int i = 0; i < cache->mat_len; ++i) {
|
||||
GPU_BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(cache->shaded_triangles_in_order);
|
||||
MEM_SAFE_FREE(cache->shaded_triangles);
|
||||
|
||||
MEM_SAFE_FREE(cache->auto_layer_names);
|
||||
MEM_SAFE_FREE(cache->auto_layer_is_srgb);
|
||||
|
||||
if (cache->texpaint_triangles) {
|
||||
for (int i = 0; i < cache->mat_len; ++i) {
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i]);
|
||||
for (int i = 0; i < cache->num_texpaint_batches; ++i) {
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles[i].batch);
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(cache->texpaint_triangles);
|
||||
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single);
|
||||
MEM_SAFE_FREE(cache->texpaint_triangles_single);
|
||||
if (cache->texpaint_triangles_single) {
|
||||
for (int i = 0; i < cache->num_texpaint_batches_single; ++i) {
|
||||
GPU_BATCH_DISCARD_SAFE(cache->texpaint_triangles_single[i].batch);
|
||||
}
|
||||
}
|
||||
MEM_SAFE_FREE(cache->texpaint_triangles_single);
|
||||
|
||||
}
|
||||
|
||||
@@ -2143,8 +2174,17 @@ static GPUVertBuf *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata,
|
||||
return cache->shaded_triangles_data;
|
||||
}
|
||||
|
||||
static int get_tile_index_from_uv(const float *uv)
|
||||
{
|
||||
int x = uv[0];
|
||||
int y = uv[1];
|
||||
CLAMP(x, 0, 9);
|
||||
CLAMP(y, 0, 9);
|
||||
return y*10 + x;
|
||||
}
|
||||
|
||||
static GPUVertBuf *mesh_batch_cache_get_tri_uv_active(
|
||||
MeshRenderData *rdata, MeshBatchCache *cache)
|
||||
MeshRenderData *rdata, MeshBatchCache *cache, bool has_tiles, bool *is_tiled)
|
||||
{
|
||||
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPUV));
|
||||
|
||||
@@ -2164,6 +2204,20 @@ static GPUVertBuf *mesh_batch_cache_get_tri_uv_active(
|
||||
}
|
||||
|
||||
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
||||
const int mat_len = mesh_render_data_mat_len_get(rdata);
|
||||
|
||||
if (is_tiled) {
|
||||
for (int i = 0; i < mat_len; i++) {
|
||||
if (is_tiled[i]) {
|
||||
has_tiles = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (has_tiles) {
|
||||
cache->tri_tiles = MEM_callocN(sizeof(int) * tri_len, "mesh cache tri tiles");
|
||||
}
|
||||
|
||||
GPUVertBuf *vbo = cache->tri_aligned_uv = GPU_vertbuf_create_with_format(&format);
|
||||
|
||||
@@ -2184,14 +2238,18 @@ static GPUVertBuf *mesh_batch_cache_get_tri_uv_active(
|
||||
if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
|
||||
continue;
|
||||
}
|
||||
const float *elem = NULL;
|
||||
for (uint t = 0; t < 3; t++) {
|
||||
const BMLoop *loop = bm_looptri[t];
|
||||
const int index = BM_elem_index_get(loop);
|
||||
if (index != -1) {
|
||||
const float *elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv;
|
||||
elem = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(loop, layer_offset))->uv;
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, elem);
|
||||
}
|
||||
}
|
||||
if (elem && has_tiles) {
|
||||
cache->tri_tiles[i] = get_tile_index_from_uv(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -2201,6 +2259,9 @@ static GPUVertBuf *mesh_batch_cache_get_tri_uv_active(
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[0]].uv);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[1]].uv);
|
||||
GPU_vertbuf_attr_set(vbo, attr_id.uv, vidx++, mloopuv[mlt->tri[2]].uv);
|
||||
if (has_tiles) {
|
||||
cache->tri_tiles[i] = get_tile_index_from_uv(mloopuv[mlt->tri[2]].uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3564,22 +3625,47 @@ static GPUIndexBuf *mesh_batch_cache_get_loose_edges(MeshRenderData *rdata, Mesh
|
||||
return cache->ledges_in_order;
|
||||
}
|
||||
|
||||
static GPUIndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
|
||||
MeshRenderData *rdata, MeshBatchCache *cache)
|
||||
static inline int get_batch_index_for_tri(bool single, bool texpaint, short mat, int mat_len, int *tri_tiles, int tri)
|
||||
{
|
||||
if (single || (mat >= mat_len)) {
|
||||
mat = 0;
|
||||
}
|
||||
if (texpaint) {
|
||||
return 100*mat + tri_tiles[tri];
|
||||
}
|
||||
return mat;
|
||||
}
|
||||
|
||||
static GPUIndexBuf **mesh_batch_cache_get_triangles_in_order_split(
|
||||
MeshRenderData *rdata, MeshBatchCache *cache, bool single, bool texpaint, int **batch_mapping, int *batch_num)
|
||||
{
|
||||
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_POLY));
|
||||
|
||||
if (cache->shaded_triangles_in_order == NULL) {
|
||||
GPUIndexBuf*** shaded_triangles;
|
||||
if (texpaint) {
|
||||
shaded_triangles = single? &cache->shaded_triangles_in_order_tiled_single : &cache->shaded_triangles_in_order_tiled;
|
||||
}
|
||||
else {
|
||||
shaded_triangles = &cache->shaded_triangles_in_order;
|
||||
}
|
||||
|
||||
if (*shaded_triangles == NULL) {
|
||||
const int poly_len = mesh_render_data_polys_len_get(rdata);
|
||||
const int tri_len = mesh_render_data_looptri_len_get(rdata);
|
||||
const int mat_len = mesh_render_data_mat_len_get(rdata);
|
||||
|
||||
int *mat_tri_len = MEM_callocN(sizeof(*mat_tri_len) * mat_len, __func__);
|
||||
cache->shaded_triangles_in_order = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
|
||||
GPUIndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * mat_len, __func__);
|
||||
if (cache->tri_tiles == NULL) {
|
||||
texpaint = false;
|
||||
}
|
||||
|
||||
/* Triangles are split according to material and/or tile index.
|
||||
* To do this, we first need to find the combinations that are actually used. */
|
||||
int index_num = (single? 1 : mat_len) * (texpaint? 100 : 1);
|
||||
int *batch_len = MEM_callocN(sizeof(int) * index_num, __func__);
|
||||
|
||||
/* Note that polygons (not triangles) are used here.
|
||||
* This OK because result is _guaranteed_ to be the same. */
|
||||
uint tri = 0;
|
||||
if (rdata->edit_bmesh) {
|
||||
BMesh *bm = rdata->edit_bmesh->bm;
|
||||
BMIter fiter;
|
||||
@@ -3587,26 +3673,67 @@ static GPUIndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
|
||||
|
||||
BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
|
||||
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
||||
const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
|
||||
mat_tri_len[ma_id] += (efa->len - 2);
|
||||
for(int j = 2; j < efa->len; j++, tri++) {
|
||||
int index = get_batch_index_for_tri(single, texpaint, efa->mat_nr, mat_len, cache->tri_tiles, tri);
|
||||
batch_len[index]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (uint i = 0; i < poly_len; i++) {
|
||||
const MPoly *mp = &rdata->mpoly[i]; ;
|
||||
const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
|
||||
mat_tri_len[ma_id] += (mp->totloop - 2);
|
||||
const MPoly *mp = &rdata->mpoly[i];
|
||||
for(int j = 2; j < mp->totloop; j++, tri++) {
|
||||
int index = get_batch_index_for_tri(single, texpaint, mp->mat_nr, mat_len, cache->tri_tiles, tri);
|
||||
batch_len[index]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, all combinations that appear in the mesh get an assigned batch index.
|
||||
* Also, we need to know each batches' length, so the batch_len array is replaced
|
||||
* with each batches' length (instead of each combinations' length).
|
||||
* This can be done in one pass since batch_num is guaranteed to be less or equal to i.
|
||||
*/
|
||||
int *index_to_batch = MEM_mallocN(sizeof(int) * index_num, __func__);
|
||||
*batch_num = 0;
|
||||
for (int i = 0; i < index_num; i++) {
|
||||
if (batch_len[i] > 0) {
|
||||
index_to_batch[i] = *batch_num;
|
||||
batch_len[*batch_num] = batch_len[i];
|
||||
(*batch_num)++;
|
||||
}
|
||||
else {
|
||||
index_to_batch[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the mapping from batches to material/tile pairs to the caller. */
|
||||
int *mapping = *batch_mapping = MEM_mallocN(sizeof(int) * 2 * (*batch_num), __func__);
|
||||
for (int i = 0; i < index_num; i++) {
|
||||
if (index_to_batch[i] >= 0) {
|
||||
int batch = index_to_batch[i];
|
||||
if (texpaint) {
|
||||
mapping[2*batch + 0] = (i / 100);
|
||||
mapping[2*batch + 1] = (i % 100);
|
||||
}
|
||||
else {
|
||||
mapping[2*batch + 0] = i;
|
||||
mapping[2*batch + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * (*batch_num), __func__);
|
||||
GPUIndexBufBuilder *elb = MEM_callocN(sizeof(*elb) * (*batch_num), __func__);
|
||||
|
||||
/* Init ELBs. */
|
||||
for (int i = 0; i < mat_len; ++i) {
|
||||
GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, mat_tri_len[i], tri_len * 3);
|
||||
for (int i = 0; i < *batch_num; ++i) {
|
||||
GPU_indexbuf_init(&elb[i], GPU_PRIM_TRIS, batch_len[i], tri_len * 3);
|
||||
}
|
||||
|
||||
/* Populate ELBs. */
|
||||
uint nidx = 0;
|
||||
tri = 0;
|
||||
if (rdata->edit_bmesh) {
|
||||
BMesh *bm = rdata->edit_bmesh->bm;
|
||||
BMIter fiter;
|
||||
@@ -3614,10 +3741,9 @@ static GPUIndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
|
||||
|
||||
BM_ITER_MESH(efa, &fiter, bm, BM_FACES_OF_MESH) {
|
||||
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
||||
const short ma_id = efa->mat_nr < mat_len ? efa->mat_nr : 0;
|
||||
for (int j = 2; j < efa->len; j++) {
|
||||
GPU_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
|
||||
nidx += 3;
|
||||
for(int j = 2; j < efa->len; j++, tri++) {
|
||||
int index = get_batch_index_for_tri(single, texpaint, efa->mat_nr, mat_len, cache->tri_tiles, tri);
|
||||
GPU_indexbuf_add_tri_verts(&elb[index_to_batch[index]], 3*tri + 0, 3*tri + 1, 3*tri + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3625,24 +3751,24 @@ static GPUIndexBuf **mesh_batch_cache_get_triangles_in_order_split_by_material(
|
||||
else {
|
||||
for (uint i = 0; i < poly_len; i++) {
|
||||
const MPoly *mp = &rdata->mpoly[i]; ;
|
||||
const short ma_id = mp->mat_nr < mat_len ? mp->mat_nr : 0;
|
||||
for (int j = 2; j < mp->totloop; j++) {
|
||||
GPU_indexbuf_add_tri_verts(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
|
||||
nidx += 3;
|
||||
for(int j = 2; j < mp->totloop; j++, tri++) {
|
||||
int index = get_batch_index_for_tri(single, texpaint, mp->mat_nr, mat_len, cache->tri_tiles, tri);
|
||||
GPU_indexbuf_add_tri_verts(&elb[index_to_batch[index]], 3*tri + 0, 3*tri + 1, 3*tri + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Build ELBs. */
|
||||
for (int i = 0; i < mat_len; ++i) {
|
||||
cache->shaded_triangles_in_order[i] = GPU_indexbuf_build(&elb[i]);
|
||||
for (int i = 0; i < *batch_num; ++i) {
|
||||
(*shaded_triangles)[i] = GPU_indexbuf_build(&elb[i]);
|
||||
}
|
||||
|
||||
MEM_freeN(mat_tri_len);
|
||||
MEM_freeN(batch_len);
|
||||
MEM_freeN(index_to_batch);
|
||||
MEM_freeN(elb);
|
||||
}
|
||||
|
||||
return cache->shaded_triangles_in_order;
|
||||
return *shaded_triangles;
|
||||
}
|
||||
|
||||
static GPUVertBuf *mesh_create_edge_pos_with_sel(
|
||||
@@ -4311,19 +4437,23 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
|
||||
|
||||
cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_len, __func__);
|
||||
|
||||
GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
|
||||
int *batch_mapping;
|
||||
int batch_num;
|
||||
GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split(rdata, cache, false, false, &batch_mapping, &batch_num);
|
||||
|
||||
GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
||||
GPUVertBuf *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache);
|
||||
|
||||
for (int i = 0; i < mat_len; ++i) {
|
||||
cache->shaded_triangles[i] = GPU_batch_create(
|
||||
for (int i = 0; i < batch_num; ++i) {
|
||||
int mat = batch_mapping[2*i + 0];
|
||||
cache->shaded_triangles[mat] = GPU_batch_create(
|
||||
GPU_PRIM_TRIS, vbo, el[i]);
|
||||
if (vbo_shading) {
|
||||
GPU_batch_vertbuf_add(cache->shaded_triangles[i], vbo_shading);
|
||||
GPU_batch_vertbuf_add(cache->shaded_triangles[mat], vbo_shading);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(batch_mapping);
|
||||
mesh_render_data_free(rdata);
|
||||
}
|
||||
|
||||
@@ -4336,7 +4466,7 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_shaded(
|
||||
return cache->shaded_triangles;
|
||||
}
|
||||
|
||||
GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
|
||||
TexpaintCacheBatch *DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me, bool *is_tiled, int *num_batches)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
||||
@@ -4346,28 +4476,33 @@ GPUBatch **DRW_mesh_batch_cache_get_surface_texpaint(Mesh *me)
|
||||
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
|
||||
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
||||
|
||||
const int mat_len = mesh_render_data_mat_len_get(rdata);
|
||||
|
||||
cache->texpaint_triangles = MEM_callocN(sizeof(*cache->texpaint_triangles) * mat_len, __func__);
|
||||
|
||||
GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split_by_material(rdata, cache);
|
||||
|
||||
GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache, false, is_tiled);
|
||||
GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
||||
for (int i = 0; i < mat_len; ++i) {
|
||||
cache->texpaint_triangles[i] = GPU_batch_create(
|
||||
|
||||
int *batch_mapping;
|
||||
GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split(rdata, cache, false, true, &batch_mapping, &cache->num_texpaint_batches);
|
||||
|
||||
cache->texpaint_triangles = MEM_callocN(sizeof(*cache->texpaint_triangles) * cache->num_texpaint_batches, __func__);
|
||||
|
||||
for (int i = 0; i < cache->num_texpaint_batches; ++i) {
|
||||
cache->texpaint_triangles[i].batch = GPU_batch_create(
|
||||
GPU_PRIM_TRIS, vbo, el[i]);
|
||||
GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
|
||||
if (vbo_uv) {
|
||||
GPU_batch_vertbuf_add(cache->texpaint_triangles[i], vbo_uv);
|
||||
GPU_batch_vertbuf_add(cache->texpaint_triangles[i].batch, vbo_uv);
|
||||
}
|
||||
cache->texpaint_triangles[i].material = batch_mapping[2*i + 0];
|
||||
cache->texpaint_triangles[i].tile = batch_mapping[2*i + 1];
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(batch_mapping);
|
||||
mesh_render_data_free(rdata);
|
||||
}
|
||||
|
||||
*num_batches = cache->num_texpaint_batches;
|
||||
return cache->texpaint_triangles;
|
||||
}
|
||||
|
||||
GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
|
||||
TexpaintCacheBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me, bool is_tiled, int *num_batches)
|
||||
{
|
||||
MeshBatchCache *cache = mesh_batch_cache_get(me);
|
||||
|
||||
@@ -4377,16 +4512,43 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Mesh *me)
|
||||
MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_POLY | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOPUV;
|
||||
MeshRenderData *rdata = mesh_render_data_create(me, datatype);
|
||||
|
||||
GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache, is_tiled, NULL);
|
||||
GPUVertBuf *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
||||
|
||||
cache->texpaint_triangles_single = GPU_batch_create(
|
||||
GPU_PRIM_TRIS, vbo, NULL);
|
||||
GPUVertBuf *vbo_uv = mesh_batch_cache_get_tri_uv_active(rdata, cache);
|
||||
if (vbo_uv) {
|
||||
GPU_batch_vertbuf_add(cache->texpaint_triangles_single, vbo_uv);
|
||||
if (cache->tri_tiles) {
|
||||
int *batch_mapping;
|
||||
GPUIndexBuf **el = mesh_batch_cache_get_triangles_in_order_split(rdata, cache, true, true, &batch_mapping, &cache->num_texpaint_batches_single);
|
||||
|
||||
cache->texpaint_triangles_single = MEM_callocN(sizeof(*cache->texpaint_triangles) * cache->num_texpaint_batches_single, __func__);
|
||||
|
||||
for (int i = 0; i < cache->num_texpaint_batches_single; ++i) {
|
||||
cache->texpaint_triangles[i].batch = GPU_batch_create(
|
||||
GPU_PRIM_TRIS, vbo, el[i]);
|
||||
if (vbo_uv) {
|
||||
GPU_batch_vertbuf_add(cache->texpaint_triangles[i].batch, vbo_uv);
|
||||
}
|
||||
cache->texpaint_triangles[i].material = batch_mapping[2*i + 0];
|
||||
cache->texpaint_triangles[i].tile = batch_mapping[2*i + 1];
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(batch_mapping);
|
||||
}
|
||||
else {
|
||||
cache->texpaint_triangles_single = MEM_callocN(sizeof(*cache->texpaint_triangles), __func__);
|
||||
cache->texpaint_triangles_single[0].batch = GPU_batch_create(
|
||||
GPU_PRIM_TRIS, vbo, NULL);
|
||||
if (vbo_uv) {
|
||||
GPU_batch_vertbuf_add(cache->texpaint_triangles_single[0].batch, vbo_uv);
|
||||
}
|
||||
cache->texpaint_triangles_single[0].material = 0;
|
||||
cache->texpaint_triangles_single[0].tile = 0;
|
||||
cache->num_texpaint_batches = 1;
|
||||
}
|
||||
|
||||
mesh_render_data_free(rdata);
|
||||
}
|
||||
|
||||
*num_batches = cache->num_texpaint_batches;
|
||||
return cache->texpaint_triangles_single;
|
||||
}
|
||||
|
||||
|
@@ -766,9 +766,18 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp, struct
|
||||
for (GPUInput *input = inputs->first; input; input = input->next) {
|
||||
/* Textures */
|
||||
if (input->ima) {
|
||||
ImageUser *tex_iuser = input->iuser;
|
||||
|
||||
/* If there's no specified iuser but we need a different tile, create a temporary one. */
|
||||
ImageUser iuser = {NULL};
|
||||
iuser.ok = true;
|
||||
iuser.tile = input->image_tile;
|
||||
if (!tex_iuser && iuser.tile != 0)
|
||||
tex_iuser = &iuser;
|
||||
|
||||
double time = 0.0; /* TODO make time variable */
|
||||
GPUTexture *tex = GPU_texture_from_blender(
|
||||
input->ima, input->iuser, input->textarget, input->image_isdata, time);
|
||||
input->ima, tex_iuser, input->textarget, input->image_isdata, time);
|
||||
|
||||
if (input->bindtex) {
|
||||
DRW_shgroup_uniform_texture(grp, input->shadername, tex);
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include "DRW_engine.h"
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "BKE_image.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
/* If builtin shaders are needed */
|
||||
@@ -118,7 +120,6 @@ typedef struct PAINT_TEXTURE_PrivateData {
|
||||
/* This keeps the references of the shading groups for
|
||||
* easy access in PAINT_TEXTURE_cache_populate() */
|
||||
DRWShadingGroup *shgroup_fallback;
|
||||
DRWShadingGroup **shgroup_image_array;
|
||||
|
||||
/* face-mask */
|
||||
DRWShadingGroup *lwire_shgrp;
|
||||
@@ -189,7 +190,6 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
|
||||
if (!stl->g_data) {
|
||||
/* Alloc transient pointers */
|
||||
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
|
||||
stl->g_data->shgroup_image_array = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
@@ -203,53 +203,6 @@ static void PAINT_TEXTURE_cache_init(void *vedata)
|
||||
* any given time (i.e. use static vars) */
|
||||
static float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
|
||||
DRW_shgroup_uniform_vec4(stl->g_data->shgroup_fallback, "color", color, 1);
|
||||
|
||||
MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
|
||||
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
Object *ob = draw_ctx->obact;
|
||||
if (ob && ob->type == OB_MESH) {
|
||||
Scene *scene = draw_ctx->scene;
|
||||
const bool use_material_slots = (scene->toolsettings->imapaint.mode == IMAGEPAINT_MODE_MATERIAL);
|
||||
const Mesh *me = ob->data;
|
||||
|
||||
stl->g_data->shgroup_image_array = MEM_mallocN(
|
||||
sizeof(*stl->g_data->shgroup_image_array) * (use_material_slots ? me->totcol : 1), __func__);
|
||||
|
||||
if (use_material_slots) {
|
||||
for (int i = 0; i < me->totcol; i++) {
|
||||
Material *ma = give_current_material(ob, i + 1);
|
||||
Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
|
||||
GPUTexture *tex = ima ?
|
||||
GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL;
|
||||
|
||||
if (tex) {
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
|
||||
DRW_shgroup_uniform_texture(grp, "image", tex);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
|
||||
stl->g_data->shgroup_image_array[i] = grp;
|
||||
}
|
||||
else {
|
||||
stl->g_data->shgroup_image_array[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Image *ima = scene->toolsettings->imapaint.canvas;
|
||||
GPUTexture *tex = ima ?
|
||||
GPU_texture_from_blender(ima, NULL, GL_TEXTURE_2D, false, 0.0f) : NULL;
|
||||
|
||||
if (tex) {
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
|
||||
DRW_shgroup_uniform_texture(grp, "image", tex);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
|
||||
stl->g_data->shgroup_image_array[0] = grp;
|
||||
}
|
||||
else {
|
||||
stl->g_data->shgroup_image_array[0] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Face Mask */
|
||||
@@ -293,29 +246,62 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
|
||||
if (use_surface) {
|
||||
if (me->mloopuv != NULL) {
|
||||
if (use_material_slots) {
|
||||
struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
|
||||
if ((me->totcol == 0) || (geom_array == NULL)) {
|
||||
struct GPUBatch *geom = DRW_cache_mesh_surface_get(ob);
|
||||
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom, ob->obmat);
|
||||
ok = true;
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < me->totcol; i++) {
|
||||
if (stl->g_data->shgroup_image_array[i]) {
|
||||
DRW_shgroup_call_add(stl->g_data->shgroup_image_array[i], geom_array[i], ob->obmat);
|
||||
//struct GPUBatch **geom_array = me->totcol ? DRW_cache_mesh_surface_texpaint_get(ob) : NULL;
|
||||
if (me->totcol) {
|
||||
bool *is_tiled = MEM_mallocN(sizeof(bool)*me->totcol, "paint texture is tiled");
|
||||
for(int i = 0; i < me->totcol; i++) {
|
||||
Material *ma = give_current_material(ob, i + 1);
|
||||
Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
|
||||
is_tiled[i] = ima && (ima->source == IMA_SRC_TILED);
|
||||
}
|
||||
|
||||
int num_batches = 0;
|
||||
struct TexpaintCacheBatch *geom_batches = DRW_cache_mesh_surface_texpaint_get(ob, is_tiled, &num_batches);
|
||||
|
||||
for (int i = 0; i < num_batches; i++) {
|
||||
ImageUser iuser = {NULL};
|
||||
iuser.ok = 1;
|
||||
iuser.tile = geom_batches[i].tile;
|
||||
|
||||
Material *ma = give_current_material(ob, geom_batches[i].material + 1);
|
||||
Image *ima = (ma && ma->texpaintslot) ? ma->texpaintslot[ma->paint_active_slot].ima : NULL;
|
||||
GPUTexture *tex = ima ?
|
||||
GPU_texture_from_blender(ima, &iuser, GL_TEXTURE_2D, false, 0.0f) : NULL;
|
||||
|
||||
if (tex) {
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
|
||||
DRW_shgroup_uniform_texture(grp, "image", tex);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
|
||||
DRW_shgroup_call_add(grp, geom_batches[i].batch, ob->obmat);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_array[i], ob->obmat);
|
||||
DRW_shgroup_call_add(stl->g_data->shgroup_fallback, geom_batches[i].batch, ob->obmat);
|
||||
}
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
struct GPUBatch *geom = DRW_cache_mesh_surface_texpaint_single_get(ob);
|
||||
if (geom && stl->g_data->shgroup_image_array[0]) {
|
||||
DRW_shgroup_call_add(stl->g_data->shgroup_image_array[0], geom, ob->obmat);
|
||||
ok = true;
|
||||
Image *ima = scene->toolsettings->imapaint.canvas;
|
||||
|
||||
if (ima) {
|
||||
bool is_tiled = (ima->source == IMA_SRC_TILED);
|
||||
int num_batches = 0;
|
||||
struct TexpaintCacheBatch *geom_batches = DRW_cache_mesh_surface_texpaint_single_get(ob, is_tiled, &num_batches);
|
||||
|
||||
for (int i = 0; i < num_batches; i++) {
|
||||
ImageUser iuser = {NULL};
|
||||
iuser.ok = 1;
|
||||
iuser.tile = geom_batches[i].tile;
|
||||
GPUTexture *tex = GPU_texture_from_blender(ima, &iuser, GL_TEXTURE_2D, false, 0.0f);
|
||||
if (tex) {
|
||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.image_sh, psl->image_faces);
|
||||
DRW_shgroup_uniform_texture(grp, "image", tex);
|
||||
DRW_shgroup_uniform_float(grp, "alpha", &draw_ctx->v3d->overlay.texture_paint_mode_opacity, 1);
|
||||
DRW_shgroup_call_add(grp, geom_batches[i].batch, ob->obmat);
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,12 +331,9 @@ static void PAINT_TEXTURE_cache_populate(void *vedata, Object *ob)
|
||||
static void PAINT_TEXTURE_cache_finish(void *vedata)
|
||||
{
|
||||
PAINT_TEXTURE_PassList *psl = ((PAINT_TEXTURE_Data *)vedata)->psl;
|
||||
PAINT_TEXTURE_StorageList *stl = ((PAINT_TEXTURE_Data *)vedata)->stl;
|
||||
|
||||
/* Do something here! dependant on the objects gathered */
|
||||
UNUSED_VARS(psl);
|
||||
|
||||
MEM_SAFE_FREE(stl->g_data->shgroup_image_array);
|
||||
}
|
||||
|
||||
/* Draw time ! Control rendering pipeline from here */
|
||||
|
@@ -48,7 +48,7 @@ struct Mask *ED_space_image_get_mask(struct SpaceImage *sima);
|
||||
void ED_space_image_set_mask(struct bContext *C, struct SpaceImage *sima, struct Mask *mask);
|
||||
|
||||
bool ED_space_image_color_sample(struct SpaceImage *sima, struct ARegion *ar, int mval[2], float r_col[3]);
|
||||
struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock);
|
||||
struct ImBuf *ED_space_image_acquire_buffer(struct SpaceImage *sima, void **r_lock, int tile);
|
||||
void ED_space_image_release_buffer(struct SpaceImage *sima, struct ImBuf *ibuf, void *lock);
|
||||
bool ED_space_image_has_buffer(struct SpaceImage *sima);
|
||||
|
||||
|
@@ -41,7 +41,7 @@ void ED_keymap_paint(struct wmKeyConfig *keyconf);
|
||||
/* paint_image.c */
|
||||
void ED_imapaint_clear_partial_redraw(void);
|
||||
void ED_imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h, bool find_old);
|
||||
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op);
|
||||
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], struct wmOperator *op, const int mouse[2]);
|
||||
|
||||
/* paint_image_undo.c */
|
||||
void ED_image_undo_push_begin(const char *name);
|
||||
|
@@ -106,7 +106,7 @@ void ED_region_visibility_change_update(struct bContext *C, struct ARegion *a
|
||||
void ED_region_info_draw(struct ARegion *ar, const char *text, float fill_color[4], const bool full_redraw);
|
||||
void ED_region_info_draw_multiline(ARegion *ar, const char *text_array[], float fill_color[4], const bool full_redraw);
|
||||
void ED_region_image_metadata_draw(int x, int y, struct ImBuf *ibuf, const rctf *frame, float zoomx, float zoomy);
|
||||
void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy);
|
||||
void ED_region_grid_draw(struct ARegion *ar, float zoomx, float zoomy, float x0, float y0);
|
||||
float ED_region_blend_alpha(struct ARegion *ar);
|
||||
void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect);
|
||||
bool ED_region_is_overlap(int spacetype, int regiontype);
|
||||
|
@@ -1272,7 +1272,7 @@ void UI_drop_color_copy(wmDrag *drag, wmDropBox *drop)
|
||||
RNA_boolean_set(drop->ptr, "gamma", drag_info->gamma_corrected);
|
||||
}
|
||||
|
||||
static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
uiBut *but = NULL;
|
||||
@@ -1313,7 +1313,7 @@ static int drop_color_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
|
||||
srgb_to_linearrgb_v3_v3(color, color);
|
||||
}
|
||||
|
||||
ED_imapaint_bucket_fill(C, color, op);
|
||||
ED_imapaint_bucket_fill(C, color, op, event->mval);
|
||||
}
|
||||
|
||||
ED_region_tag_redraw(ar);
|
||||
|
@@ -275,9 +275,12 @@ static void refresh_images(BakeImages *bake_images)
|
||||
int i;
|
||||
for (i = 0; i < bake_images->size; i++) {
|
||||
Image *ima = bake_images->data[i].image;
|
||||
if (ima->ok == IMA_OK_LOADED) {
|
||||
GPU_free_image(ima);
|
||||
DEG_id_tag_update(&ima->id, 0);
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
if (tile->ok == IMA_OK_LOADED) {
|
||||
GPU_free_image(ima);
|
||||
DEG_id_tag_update(&ima->id, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -982,8 +982,12 @@ static void icon_preview_startjob(void *customdata, short *stop, short *do_updat
|
||||
ImBuf *ibuf = NULL;
|
||||
ImageUser iuser = {NULL};
|
||||
|
||||
if (ima == NULL)
|
||||
return;
|
||||
|
||||
ImageTile *tile = BKE_image_get_tile(ima, 0);
|
||||
/* ima->ok is zero when Image cannot load */
|
||||
if (ima == NULL || ima->ok == 0)
|
||||
if (tile->ok == 0)
|
||||
return;
|
||||
|
||||
/* setup dummy image user */
|
||||
|
@@ -2735,15 +2735,15 @@ void ED_region_image_metadata_draw(int x, int y, ImBuf *ibuf, const rctf *frame,
|
||||
GPU_matrix_pop();
|
||||
}
|
||||
|
||||
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy)
|
||||
void ED_region_grid_draw(ARegion *ar, float zoomx, float zoomy, float x0, float y0)
|
||||
{
|
||||
float gridsize, gridstep = 1.0f / 32.0f;
|
||||
float fac, blendfac;
|
||||
int x1, y1, x2, y2;
|
||||
|
||||
/* the image is located inside (0, 0), (1, 1) as set by view2d */
|
||||
UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x1, &y1);
|
||||
UI_view2d_view_to_region(&ar->v2d, 1.0f, 1.0f, &x2, &y2);
|
||||
/* the image is located inside (x0, y0), (x0+1, y0+1) as set by view2d */
|
||||
UI_view2d_view_to_region(&ar->v2d, x0, y0, &x1, &y1);
|
||||
UI_view2d_view_to_region(&ar->v2d, x0+1.0f, y0+1.0f, &x2, &y2);
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
|
@@ -163,7 +163,7 @@ void ED_imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int
|
||||
IMB_freeImBuf(tmpibuf);
|
||||
}
|
||||
|
||||
void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint)
|
||||
void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, ImageUser *iuser, short texpaint)
|
||||
{
|
||||
if (imapaintpartial.x1 != imapaintpartial.x2 &&
|
||||
imapaintpartial.y1 != imapaintpartial.y2)
|
||||
@@ -182,7 +182,7 @@ void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short te
|
||||
int h = imapaintpartial.y2 - imapaintpartial.y1;
|
||||
if (w && h) {
|
||||
/* Testing with partial update in uv editor too */
|
||||
GPU_paint_update_image(image, (sima ? &sima->iuser : NULL), imapaintpartial.x1, imapaintpartial.y1, w, h);
|
||||
GPU_paint_update_image(image, iuser, imapaintpartial.x1, imapaintpartial.y1, w, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -587,7 +587,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
|
||||
float color[3];
|
||||
|
||||
srgb_to_linearrgb_v3_v3(color, BKE_brush_color_get(scene, brush));
|
||||
paint_2d_bucket_fill(C, color, brush, pop->prevmouse, pop->custom_paint);
|
||||
paint_2d_bucket_fill(C, color, brush, pop->startmouse, pop->prevmouse, pop->custom_paint);
|
||||
}
|
||||
else {
|
||||
paint_proj_stroke(
|
||||
@@ -1224,7 +1224,7 @@ void PAINT_OT_brush_colors_flip(wmOperatorType *ot)
|
||||
}
|
||||
|
||||
|
||||
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op)
|
||||
void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op, const int mouse[2])
|
||||
{
|
||||
wmWindowManager *wm = CTX_wm_manager(C);
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
@@ -1234,7 +1234,8 @@ void ED_imapaint_bucket_fill(struct bContext *C, float color[3], wmOperator *op)
|
||||
|
||||
ED_image_undo_push_begin(op->type->name);
|
||||
|
||||
paint_2d_bucket_fill(C, color, NULL, NULL, NULL);
|
||||
float mouse_init[2] = {mouse[0], mouse[1]};
|
||||
paint_2d_bucket_fill(C, color, NULL, mouse_init, NULL, NULL);
|
||||
|
||||
BKE_undosys_step_push(wm->undo_stack, C, op->type->name);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -193,6 +193,8 @@ BLI_INLINE unsigned char f_to_char(const float val)
|
||||
* because 'partRedrawRect' and 'touch' values would not be thread safe */
|
||||
typedef struct ProjPaintImage {
|
||||
Image *ima;
|
||||
int tile;
|
||||
ImageUser iuser;
|
||||
ImBuf *ibuf;
|
||||
ImagePaintPartialRedraw *partRedrawRect;
|
||||
volatile void **undoRect; /* only used to build undo tiles during painting */
|
||||
@@ -468,6 +470,16 @@ BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_
|
||||
|
||||
/* Finish projection painting structs */
|
||||
|
||||
static int project_paint_face_paint_tile(Image *ima, const float *uv)
|
||||
{
|
||||
if (!ima || ima->source != IMA_SRC_TILED)
|
||||
return 0;
|
||||
/* Currently, faces are assumed to belong to one tile, so checking the first loop is enough. */
|
||||
int tx = (int) uv[0];
|
||||
int ty = (int) uv[1];
|
||||
return 10*ty + tx;
|
||||
}
|
||||
|
||||
static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
|
||||
{
|
||||
const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
|
||||
@@ -664,8 +676,18 @@ static bool project_paint_PickColor(
|
||||
interp_v2_v2v2v2(uv, UNPACK3(lt_tri_uv), w);
|
||||
|
||||
ima = project_paint_face_paint_image(ps, tri_index);
|
||||
ibuf = BKE_image_get_first_ibuf(ima); /* we must have got the imbuf before getting here */
|
||||
if (!ibuf) return 0;
|
||||
int tile_number = project_paint_face_paint_tile(ima, lt_tri_uv[0]);
|
||||
ImageUser iuser = {NULL};
|
||||
iuser.ok = 1;
|
||||
iuser.tile = tile_number;
|
||||
ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
|
||||
if (!ibuf) {
|
||||
iuser.tile = 0;
|
||||
ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
|
||||
if (!ibuf) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (interp) {
|
||||
float x, y;
|
||||
@@ -1052,6 +1074,8 @@ static bool check_seam(
|
||||
const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
|
||||
Image *tpage = project_paint_face_paint_image(ps, tri_index);
|
||||
Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
|
||||
int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]);
|
||||
int orig_tile = project_paint_face_paint_tile(orig_tpage, orig_lt_tri_uv[0]);
|
||||
|
||||
BLI_assert(i1_fidx != -1);
|
||||
|
||||
@@ -1069,6 +1093,7 @@ static bool check_seam(
|
||||
|
||||
/* first test if they have the same image */
|
||||
if ((orig_tpage == tpage) &&
|
||||
(orig_tile == tile) &&
|
||||
cmp_uv(orig_lt_tri_uv[orig_i1_fidx], lt_tri_uv[i1_fidx]) &&
|
||||
cmp_uv(orig_lt_tri_uv[orig_i2_fidx], lt_tri_uv[i2_fidx]))
|
||||
{
|
||||
@@ -2921,6 +2946,7 @@ static void project_bucket_init(
|
||||
ImBuf *ibuf = NULL;
|
||||
Image *tpage_last = NULL, *tpage;
|
||||
ImBuf *tmpibuf = NULL;
|
||||
int tile_last = 0;
|
||||
|
||||
if (ps->image_tot == 1) {
|
||||
/* Simple loop, no context switching */
|
||||
@@ -2938,17 +2964,33 @@ static void project_bucket_init(
|
||||
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
|
||||
tri_index = GET_INT_FROM_POINTER(node->link);
|
||||
|
||||
const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
|
||||
const float *lt_tri_uv[3] = { PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt) };
|
||||
|
||||
/* Image context switching */
|
||||
tpage = project_paint_face_paint_image(ps, tri_index);
|
||||
if (tpage_last != tpage) {
|
||||
int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]);
|
||||
if (tpage_last != tpage || tile_last != tile) {
|
||||
tpage_last = tpage;
|
||||
tile_last = tile;
|
||||
|
||||
for (image_index = 0; image_index < ps->image_tot; image_index++) {
|
||||
if (ps->projImages[image_index].ima == tpage_last) {
|
||||
ibuf = ps->projImages[image_index].ibuf;
|
||||
ProjPaintImage *projIma = &ps->projImages[image_index];
|
||||
if ((projIma->ima == tpage) && (projIma->tile == tile)) {
|
||||
ibuf = projIma->ibuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ibuf == NULL) {
|
||||
/* Failed to find the specific tile, fall back to the primary tile. */
|
||||
for (image_index = 0; image_index < ps->image_tot; image_index++) {
|
||||
ProjPaintImage *projIma = &ps->projImages[image_index];
|
||||
if ((projIma->ima == tpage) && (projIma->tile == 0)) {
|
||||
ibuf = projIma->ibuf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* context switching done */
|
||||
|
||||
@@ -3624,22 +3666,36 @@ static bool project_paint_winclip(
|
||||
#endif //PROJ_DEBUG_WINCLIP
|
||||
|
||||
|
||||
typedef struct PrepareImageEntry {
|
||||
struct PrepareImageEntry *next, *prev;
|
||||
Image *ima;
|
||||
int tile;
|
||||
} PrepareImageEntry;
|
||||
|
||||
static void project_paint_build_proj_ima(
|
||||
ProjPaintState *ps, MemArena *arena,
|
||||
LinkNode *image_LinkList)
|
||||
ListBase *used_images)
|
||||
{
|
||||
ProjPaintImage *projIma;
|
||||
LinkNode *node;
|
||||
PrepareImageEntry *entry;
|
||||
int i;
|
||||
|
||||
/* build an array of images we use */
|
||||
projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
|
||||
|
||||
for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
|
||||
for (entry = used_images->first, i = 0; entry; entry = entry->next, i++, projIma++) {
|
||||
memset(&projIma->iuser, 0, sizeof(ImageUser));
|
||||
projIma->iuser.ok = 1;
|
||||
projIma->iuser.tile = entry->tile;
|
||||
int size;
|
||||
projIma->ima = node->link;
|
||||
projIma->ima = entry->ima;
|
||||
projIma->tile = entry->tile;
|
||||
projIma->touch = 0;
|
||||
projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
|
||||
projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, &projIma->iuser, NULL);
|
||||
if (!projIma->ibuf) {
|
||||
projIma->iuser.tile = 0;
|
||||
projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, &projIma->iuser, NULL);
|
||||
}
|
||||
size = sizeof(void **) * IMAPAINT_TILE_NUMBER(projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(projIma->ibuf->y);
|
||||
projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED);
|
||||
partial_redraw_array_init(projIma->partRedrawRect);
|
||||
@@ -3660,15 +3716,18 @@ static void project_paint_prepare_all_faces(
|
||||
const bool is_multi_view)
|
||||
{
|
||||
/* Image Vars - keep track of images we have used */
|
||||
LinkNodePair image_LinkList = {NULL, NULL};
|
||||
ListBase used_images = {NULL};
|
||||
|
||||
Image *tpage_last = NULL, *tpage;
|
||||
TexPaintSlot *slot_last = NULL;
|
||||
TexPaintSlot *slot = NULL;
|
||||
int tile_last = -1, tile;
|
||||
const MLoopTri *lt;
|
||||
int image_index = -1, tri_index;
|
||||
int prev_poly = -1;
|
||||
|
||||
BLI_assert(ps->image_tot == 0);
|
||||
|
||||
for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
|
||||
bool is_face_sel;
|
||||
|
||||
@@ -3709,6 +3768,8 @@ static void project_paint_prepare_all_faces(
|
||||
|
||||
ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
|
||||
|
||||
tile = project_paint_face_paint_tile(tpage, mloopuv_base[lt->tri[0]].uv);
|
||||
|
||||
if (project_paint_clone_face_skip(ps, layer_clone, slot, tri_index)) {
|
||||
continue;
|
||||
}
|
||||
@@ -3766,17 +3827,24 @@ static void project_paint_prepare_all_faces(
|
||||
}
|
||||
}
|
||||
|
||||
if (tpage_last != tpage) {
|
||||
if (tpage_last != tpage || tile_last != tile) {
|
||||
image_index = 0;
|
||||
for (PrepareImageEntry *e = used_images.first; e; e = e->next, image_index++) {
|
||||
if (e->ima == tpage && e->tile == tile) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
image_index = BLI_linklist_index(image_LinkList.list, tpage);
|
||||
|
||||
if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */
|
||||
BLI_linklist_append(&image_LinkList, tpage);
|
||||
image_index = ps->image_tot;
|
||||
if (image_index == ps->image_tot) {
|
||||
PrepareImageEntry *e = MEM_callocN(sizeof(PrepareImageEntry), "PrepareImageEntry");
|
||||
e->ima = tpage;
|
||||
e->tile = tile;
|
||||
BLI_addtail(&used_images, e);
|
||||
ps->image_tot++;
|
||||
}
|
||||
|
||||
tpage_last = tpage;
|
||||
tile_last = tile;
|
||||
}
|
||||
|
||||
if (image_index != -1) {
|
||||
@@ -3789,11 +3857,11 @@ static void project_paint_prepare_all_faces(
|
||||
|
||||
/* build an array of images we use*/
|
||||
if (ps->is_shared_user == false) {
|
||||
project_paint_build_proj_ima(ps, arena, image_LinkList.list);
|
||||
project_paint_build_proj_ima(ps, arena, &used_images);
|
||||
}
|
||||
|
||||
/* we have built the array, discard the linked list */
|
||||
BLI_linklist_free(image_LinkList.list, NULL);
|
||||
BLI_freelistN(&used_images);
|
||||
}
|
||||
|
||||
/* run once per stroke before projection painting */
|
||||
@@ -4036,7 +4104,7 @@ static bool project_image_refresh_tagged(ProjPaintState *ps)
|
||||
pr = &(projIma->partRedrawRect[i]);
|
||||
if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
|
||||
set_imapaintpartial(pr);
|
||||
imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
|
||||
imapaint_image_update(NULL, projIma->ima, projIma->ibuf, &projIma->iuser, true);
|
||||
redraw = 1;
|
||||
}
|
||||
|
||||
@@ -5644,7 +5712,7 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain)
|
||||
}
|
||||
ima = BKE_image_add_generated(
|
||||
bmain, width, height, imagename, alpha ? 32 : 24, use_float,
|
||||
gen_type, color, false);
|
||||
gen_type, color, false, false);
|
||||
|
||||
return ima;
|
||||
}
|
||||
|
@@ -181,7 +181,7 @@ typedef struct ImagePaintPartialRedraw {
|
||||
#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS)
|
||||
|
||||
bool image_texture_paint_poll(struct bContext *C);
|
||||
void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint);
|
||||
void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, struct ImageUser *iuser, short texpaint);
|
||||
struct ImagePaintPartialRedraw *get_imapaintpartial(void);
|
||||
void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr);
|
||||
void imapaint_region_tiles(struct ImBuf *ibuf, int x, int y, int w, int h, int *tx, int *ty, int *tw, int *th);
|
||||
@@ -193,7 +193,7 @@ void paint_2d_stroke(
|
||||
void *ps, const float prev_mval[2], const float mval[2],
|
||||
const bool eraser, float pressure, float distance, float size);
|
||||
void paint_2d_bucket_fill(
|
||||
const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], void *ps);
|
||||
const struct bContext *C, const float color[3], struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
|
||||
void paint_2d_gradient_fill(
|
||||
const struct bContext *C, struct Brush *br, const float mouse_init[2], const float mouse_final[2], void *ps);
|
||||
void *paint_proj_new_stroke(
|
||||
|
@@ -1790,7 +1790,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
|
||||
|
||||
/* if no clip, nothing to do */
|
||||
if (!clip) {
|
||||
ED_region_grid_draw(ar, zoomx, zoomy);
|
||||
ED_region_grid_draw(ar, zoomx, zoomy, 0.0f, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1836,7 +1836,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar)
|
||||
draw_movieclip_muted(ar, width, height, zoomx, zoomy);
|
||||
}
|
||||
else {
|
||||
ED_region_grid_draw(ar, zoomx, zoomy);
|
||||
ED_region_grid_draw(ar, zoomx, zoomy, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
if (width && height) {
|
||||
|
@@ -112,7 +112,7 @@ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf,
|
||||
if (ibuf->zbuf || ibuf->zbuf_float)
|
||||
ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs);
|
||||
|
||||
if (ima->source == IMA_SRC_SEQUENCE) {
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
|
||||
const char *file = BLI_last_slash(ibuf->name);
|
||||
if (file == NULL)
|
||||
file = ibuf->name;
|
||||
|
@@ -49,6 +49,7 @@
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_listbase.h"
|
||||
|
||||
#include "IMB_imbuf.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
@@ -479,7 +480,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, float x1, float y1, int rec
|
||||
MEM_freeN(rectf);
|
||||
}
|
||||
|
||||
static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy)
|
||||
static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, Scene *scene, ImBuf *ibuf, float fx, float fy, float zoomx, float zoomy, const char *label)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
@@ -547,6 +548,24 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar,
|
||||
if (sima->flag & SI_USE_ALPHA)
|
||||
GPU_blend(false);
|
||||
}
|
||||
|
||||
if (label && label[0]) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
BLF_size(blf_mono_font, 25 * U.pixelsize, U.dpi);
|
||||
|
||||
int textwidth = BLF_width(blf_mono_font, label, strlen(label)) + 10;
|
||||
float opacity;
|
||||
float stepx = BLI_rcti_size_x(&ar->v2d.mask) / BLI_rctf_size_x(&ar->v2d.cur);
|
||||
if (textwidth < 0.5f*(stepx - 10)) opacity = 1.0f;
|
||||
else if (textwidth < (stepx - 10)) opacity = 2.0f - 2.0f*(textwidth / (stepx - 10));
|
||||
else opacity = 0.0f;
|
||||
BLF_color4ub(blf_mono_font, 220, 220, 220, 150*opacity);
|
||||
BLF_position(blf_mono_font, (int) (x + 10), (int) (y + 10), 0);
|
||||
BLF_draw_ascii(blf_mono_font, label, strlen(label));
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
/* draw uv edit */
|
||||
@@ -586,9 +605,13 @@ void draw_image_sample_line(SpaceImage *sima)
|
||||
immUniformArray4fv("colors", (float *)(float[][4]){{1.0f, 1.0f, 1.0f, 1.0f}, {0.0f, 0.0f, 0.0f, 1.0f}}, 2);
|
||||
immUniform1f("dash_width", 2.0f);
|
||||
|
||||
float co[2][2];
|
||||
add_v2_v2v2(co[0], hist->co[0], hist->draw_offset);
|
||||
add_v2_v2v2(co[1], hist->co[1], hist->draw_offset);
|
||||
|
||||
immBegin(GPU_PRIM_LINES, 2);
|
||||
immVertex2fv(shdr_dashed_pos, hist->co[0]);
|
||||
immVertex2fv(shdr_dashed_pos, hist->co[1]);
|
||||
immVertex2fv(shdr_dashed_pos, co[0]);
|
||||
immVertex2fv(shdr_dashed_pos, co[1]);
|
||||
immEnd();
|
||||
|
||||
immUnbindProgram();
|
||||
@@ -633,6 +656,69 @@ static void draw_image_paint_helpers(const bContext *C, ARegion *ar, Scene *scen
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_udim_tile_grid(unsigned int pos_attr, unsigned int color_attr,
|
||||
ARegion *ar, int x, int y,
|
||||
float stepx, float stepy, const float color[3])
|
||||
{
|
||||
float x1, y1;
|
||||
UI_view2d_view_to_region_fl(&ar->v2d, x, y, &x1, &y1);
|
||||
int gridpos[5][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}};
|
||||
for(int i = 0; i < 4; i++) {
|
||||
immAttrib3fv(color_attr, color);
|
||||
immVertex2f(pos_attr, x1 + gridpos[i][0]*stepx, y1 + gridpos[i][1]*stepy);
|
||||
immAttrib3fv(color_attr, color);
|
||||
immVertex2f(pos_attr, x1 + gridpos[i+1][0]*stepx, y1 + gridpos[i+1][1]*stepy);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_image_tiles(ARegion *ar, SpaceImage *sima, Image *ima)
|
||||
{
|
||||
int num_tiles;
|
||||
if (ima) {
|
||||
num_tiles = BLI_listbase_count(&ima->tiles);
|
||||
}
|
||||
else {
|
||||
num_tiles = sima->tile_grid_shape[0] * sima->tile_grid_shape[1];
|
||||
}
|
||||
|
||||
float stepx = BLI_rcti_size_x(&ar->v2d.mask) / BLI_rctf_size_x(&ar->v2d.cur);
|
||||
float stepy = BLI_rcti_size_y(&ar->v2d.mask) / BLI_rctf_size_y(&ar->v2d.cur);
|
||||
|
||||
GPUVertFormat *format = immVertexFormat();
|
||||
unsigned int pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
|
||||
|
||||
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
|
||||
immBegin(GPU_PRIM_LINES, 8*(num_tiles + 1));
|
||||
|
||||
float theme_color[3], selected_color[3];
|
||||
UI_GetThemeColorShade3fv(TH_BACK, 60.0f, theme_color);
|
||||
UI_GetThemeColor3fv(TH_FACE_SELECT, selected_color);
|
||||
|
||||
if (ima) {
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
int x = tile->tile_number % 10;
|
||||
int y = tile->tile_number / 10;
|
||||
draw_udim_tile_grid(pos, color, ar, x, y, stepx, stepy, theme_color);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y = 0; y < sima->tile_grid_shape[1]; y++) {
|
||||
for (int x = 0; x < sima->tile_grid_shape[0]; x++) {
|
||||
draw_udim_tile_grid(pos, color, ar, x, y, stepx, stepy, theme_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int cur_x = sima->curtile % 10, cur_y = sima->curtile / 10;
|
||||
draw_udim_tile_grid(pos, color, ar, cur_x, cur_y, stepx, stepy, selected_color);
|
||||
|
||||
immEnd();
|
||||
immUnbindProgram();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* draw main image region */
|
||||
|
||||
void draw_image_main(const bContext *C, ARegion *ar)
|
||||
@@ -692,14 +778,35 @@ void draw_image_main(const bContext *C, ARegion *ar)
|
||||
BKE_image_multiview_index(ima, &sima->iuser);
|
||||
}
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
|
||||
int main_w = 0;
|
||||
int main_h = 0;
|
||||
|
||||
/* draw the image or grid */
|
||||
if (ibuf == NULL) {
|
||||
ED_region_grid_draw(ar, zoomx, zoomy);
|
||||
if (ima) {
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
int x = tile->tile_number % 10;
|
||||
int y = tile->tile_number / 10;
|
||||
ED_region_grid_draw(ar, zoomx, zoomy, x, y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y = 0; y < sima->tile_grid_shape[1]; y++) {
|
||||
for (int x = 0; x < sima->tile_grid_shape[0]; x++) {
|
||||
ED_region_grid_draw(ar, zoomx, zoomy, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy);
|
||||
main_w = ibuf->x;
|
||||
main_h = ibuf->y;
|
||||
|
||||
char label[64];
|
||||
BKE_image_get_tile_label(ima, 0, label, sizeof(label));
|
||||
draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy, label);
|
||||
|
||||
if (sima->flag & SI_DRAW_METADATA) {
|
||||
int x, y;
|
||||
@@ -714,6 +821,28 @@ void draw_image_main(const bContext *C, ARegion *ar)
|
||||
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
|
||||
if (ima && ima->source == IMA_SRC_TILED) {
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
if (tile->tile_number == 0)
|
||||
continue;
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock, tile->tile_number);
|
||||
if (ibuf) {
|
||||
int x_pos = tile->tile_number % 10;
|
||||
int y_pos = tile->tile_number / 10;
|
||||
char label[64];
|
||||
BKE_image_get_tile_label(ima, tile, label, sizeof(label));
|
||||
|
||||
float tile_zoomx = (zoomx * main_w) / ibuf->x;
|
||||
float tile_zoomy = (zoomy * main_h) / ibuf->y;
|
||||
draw_image_buffer(C, sima, ar, scene, ibuf, x_pos, y_pos, tile_zoomx, tile_zoomy, label);
|
||||
}
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
}
|
||||
}
|
||||
|
||||
draw_image_tiles(ar, sima, ima);
|
||||
|
||||
/* paint helpers */
|
||||
if (show_paint)
|
||||
draw_image_paint_helpers(C, ar, scene, zoomx, zoomy);
|
||||
|
@@ -105,7 +105,7 @@ void ED_space_image_set_mask(bContext *C, SpaceImage *sima, Mask *mask)
|
||||
}
|
||||
}
|
||||
|
||||
ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock)
|
||||
ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock, int tile)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
|
||||
@@ -115,7 +115,9 @@ ImBuf *ED_space_image_acquire_buffer(SpaceImage *sima, void **r_lock)
|
||||
return BIF_render_spare_imbuf();
|
||||
else
|
||||
#endif
|
||||
sima->iuser.tile = tile;
|
||||
ibuf = BKE_image_acquire_ibuf(sima->image, &sima->iuser, r_lock);
|
||||
sima->iuser.tile = 0;
|
||||
|
||||
if (ibuf) {
|
||||
if (ibuf->rect || ibuf->rect_float)
|
||||
@@ -142,7 +144,7 @@ bool ED_space_image_has_buffer(SpaceImage *sima)
|
||||
void *lock;
|
||||
bool has_buffer;
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
has_buffer = (ibuf != NULL);
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
|
||||
@@ -155,7 +157,8 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height)
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
/* TODO(lukas): Support tiled images with different sizes */
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
|
||||
if (ibuf && ibuf->x > 0 && ibuf->y > 0) {
|
||||
*width = ibuf->x;
|
||||
|
@@ -97,6 +97,11 @@ void IMAGE_OT_read_viewlayers(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_render_border(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_clear_render_border(struct wmOperatorType *ot);
|
||||
|
||||
void IMAGE_OT_add_tile(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_remove_tile(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_fill_tile(struct wmOperatorType *ot);
|
||||
void IMAGE_OT_select_tile(struct wmOperatorType *ot);
|
||||
|
||||
/* image_panels.c */
|
||||
struct ImageUser *ntree_get_active_iuser(struct bNodeTree *ntree);
|
||||
void image_buttons_register(struct ARegionType *art);
|
||||
|
@@ -45,6 +45,9 @@
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_fileops_types.h"
|
||||
#include "BLI_linklist.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
@@ -223,7 +226,7 @@ static bool space_image_file_exists_poll(bContext *C)
|
||||
bool ret = false;
|
||||
char name[FILE_MAX];
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
if (ibuf) {
|
||||
BLI_strncpy(name, ibuf->name, FILE_MAX);
|
||||
BLI_path_abs(name, BKE_main_blendfile_path(bmain));
|
||||
@@ -1150,6 +1153,52 @@ static int image_cmp_frame(const void *a, const void *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int image_get_udim(const char *filepath, LinkNodePair *udim_tiles)
|
||||
{
|
||||
if (strstr(filepath, "1001") == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char filename[FILE_MAX], dirname[FILE_MAXDIR];
|
||||
BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
|
||||
|
||||
bool is_udim = true;
|
||||
int max_udim = 0;
|
||||
|
||||
unsigned short digits;
|
||||
char base_head[FILE_MAX], base_tail[FILE_MAX];
|
||||
int id = BLI_stringdec(filename, base_head, base_tail, &digits);
|
||||
if (id == 1001) {
|
||||
struct direntry *dir;
|
||||
uint totfile = BLI_filelist_dir_contents(dirname, &dir);
|
||||
for (int i = 0; i < totfile; i++) {
|
||||
if (!(dir[i].type & S_IFREG)) {
|
||||
continue;
|
||||
}
|
||||
char head[FILE_MAX], tail[FILE_MAX];
|
||||
id = BLI_stringdec(dir[i].relname, head, tail, &digits);
|
||||
|
||||
if (digits > 4 ||
|
||||
!(STREQLEN(base_head, head, FILE_MAX)) ||
|
||||
!(STREQLEN(base_tail, tail, FILE_MAX))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id < 1001 || id >= 2000) {
|
||||
is_udim = false;
|
||||
break;
|
||||
}
|
||||
|
||||
BLI_linklist_append(udim_tiles, SET_INT_IN_POINTER(id - 1001));
|
||||
max_udim = max_ii(max_udim, id);
|
||||
}
|
||||
|
||||
BLI_filelist_free(dir, totfile);
|
||||
}
|
||||
|
||||
return is_udim? (max_udim - 1001) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the start (offset) and the length of the sequence of continuous frames in the list of frames
|
||||
*
|
||||
@@ -1157,21 +1206,27 @@ static int image_cmp_frame(const void *a, const void *b)
|
||||
* \param ofs: [out] offset the first frame number in the sequence.
|
||||
* \return the number of contiguous frames in the sequence
|
||||
*/
|
||||
static int image_sequence_get_len(ListBase *frames, int *ofs)
|
||||
static int image_sequence_get_len(ImageFrameRange *frame_range, int *ofs, LinkNodePair *udim_tiles)
|
||||
{
|
||||
ImageFrame *frame;
|
||||
|
||||
BLI_listbase_sort(frames, image_cmp_frame);
|
||||
BLI_listbase_sort(&frame_range->frames, image_cmp_frame);
|
||||
|
||||
frame = frames->first;
|
||||
frame = frame_range->frames.first;
|
||||
if (frame) {
|
||||
int frame_curr = frame->framenr;
|
||||
(*ofs) = frame_curr;
|
||||
while (frame && (frame->framenr == frame_curr)) {
|
||||
frame_curr++;
|
||||
frame = frame->next;
|
||||
|
||||
if (udim_tiles && (frame_curr == 1001)) {
|
||||
return 1 + image_get_udim(frame_range->filepath, udim_tiles);
|
||||
}
|
||||
else {
|
||||
while (frame && (frame->framenr == frame_curr)) {
|
||||
frame_curr++;
|
||||
frame = frame->next;
|
||||
}
|
||||
return frame_curr - (*ofs);
|
||||
}
|
||||
return frame_curr - (*ofs);
|
||||
}
|
||||
*ofs = 0;
|
||||
return 0;
|
||||
@@ -1179,7 +1234,8 @@ static int image_sequence_get_len(ListBase *frames, int *ofs)
|
||||
|
||||
static Image *image_open_single(
|
||||
Main *bmain, wmOperator *op, const char *filepath, const char *relbase,
|
||||
bool is_relative_path, bool use_multiview, int frame_seq_len)
|
||||
bool is_relative_path, bool use_multiview, int frame_seq_len,
|
||||
int frame_seq_ofs, LinkNodePair *udim_tiles)
|
||||
{
|
||||
bool exists = false;
|
||||
Image *ima = NULL;
|
||||
@@ -1215,7 +1271,15 @@ static Image *image_open_single(
|
||||
}
|
||||
|
||||
if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
|
||||
ima->source = IMA_SRC_SEQUENCE;
|
||||
if (udim_tiles && frame_seq_ofs == 1001) {
|
||||
ima->source = IMA_SRC_TILED;
|
||||
for (LinkNode *node = udim_tiles->list; node; node = node->next) {
|
||||
BKE_image_add_tile(ima, GET_INT_FROM_POINTER(node->link), NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ima->source = IMA_SRC_SEQUENCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,6 +1302,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
|
||||
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
|
||||
const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview");
|
||||
const bool use_udim = RNA_boolean_get(op->ptr, "use_udim");
|
||||
|
||||
if (!op->customdata)
|
||||
image_open_init(C, op);
|
||||
@@ -1254,7 +1319,9 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all);
|
||||
for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range; frame_range = frame_range->next) {
|
||||
int frame_range_ofs;
|
||||
int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs);
|
||||
LinkNodePair udim_tiles = {NULL};
|
||||
int frame_range_seq_len = image_sequence_get_len(frame_range, &frame_range_ofs,
|
||||
use_udim? &udim_tiles : NULL);
|
||||
BLI_freelistN(&frame_range->frames);
|
||||
|
||||
char filepath_range[FILE_MAX];
|
||||
@@ -1266,7 +1333,10 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
|
||||
Image *ima_range = image_open_single(
|
||||
bmain, op, filepath_range, BKE_main_blendfile_path(bmain),
|
||||
is_relative_path, use_multiview, frame_range_seq_len);
|
||||
is_relative_path, use_multiview, frame_range_seq_len, frame_range_ofs,
|
||||
use_udim? &udim_tiles : NULL);
|
||||
|
||||
BLI_linklist_free(udim_tiles.list, NULL);
|
||||
|
||||
/* take the first image */
|
||||
if ((ima == NULL) && ima_range) {
|
||||
@@ -1278,10 +1348,17 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
BLI_freelistN(&frame_ranges_all);
|
||||
}
|
||||
else {
|
||||
int sequence_len = 1;
|
||||
LinkNodePair udim_tiles = {NULL};
|
||||
if (use_udim) {
|
||||
sequence_len = image_get_udim(filepath, &udim_tiles);
|
||||
}
|
||||
/* for drag & drop etc. */
|
||||
ima = image_open_single(
|
||||
bmain, op, filepath, BKE_main_blendfile_path(bmain),
|
||||
is_relative_path, use_multiview, 1);
|
||||
is_relative_path, use_multiview, 1, sequence_len, &udim_tiles);
|
||||
|
||||
BLI_linklist_free(udim_tiles.list, NULL);
|
||||
}
|
||||
|
||||
if (ima == NULL) {
|
||||
@@ -1331,7 +1408,7 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* initialize because of new image */
|
||||
if (iuser) {
|
||||
iuser->frames = frame_seq_len;
|
||||
iuser->frames = (ima->source == IMA_SRC_SEQUENCE)? frame_seq_len : 1;
|
||||
iuser->sfra = 1;
|
||||
iuser->framenr = 1;
|
||||
if (ima->source == IMA_SRC_MOVIE) {
|
||||
@@ -1464,6 +1541,7 @@ void IMAGE_OT_open(wmOperatorType *ot)
|
||||
|
||||
RNA_def_boolean(ot->srna, "use_sequence_detection", true, "Detect Sequences",
|
||||
"Automatically detect animated sequences in selected images (based on file names)");
|
||||
RNA_def_boolean(ot->srna, "use_udim", true, "Detect UDIMs", "Detect selected UDIM files and load all matching tiles");
|
||||
}
|
||||
|
||||
/******************** Match movie length operator ********************/
|
||||
@@ -1630,7 +1708,7 @@ static int save_image_options_init(Main *bmain, SaveImageOptions *simopts, Space
|
||||
const bool guess_path, const bool save_as_render)
|
||||
{
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
|
||||
if (ibuf) {
|
||||
Image *ima = sima->image;
|
||||
@@ -1698,6 +1776,11 @@ static int save_image_options_init(Main *bmain, SaveImageOptions *simopts, Space
|
||||
BLI_snprintf(simopts->filepath, sizeof(simopts->filepath), "//%s", ima->id.name + 2);
|
||||
BLI_path_abs(simopts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain));
|
||||
}
|
||||
|
||||
/* append UDIM numbering if not present */
|
||||
if (ima->source == IMA_SRC_TILED && (BLI_stringdec(ima->name, NULL, NULL, NULL) != 1001)) {
|
||||
strncat(simopts->filepath, ".1001", sizeof(simopts->filepath) - 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* color management */
|
||||
@@ -1811,18 +1894,16 @@ static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf)
|
||||
* \note ``ima->name`` and ``ibuf->name`` should end up the same.
|
||||
* \note for multiview the first ``ibuf`` is important to get the settings.
|
||||
*/
|
||||
static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath)
|
||||
static bool save_image_single(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath, int tile)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Image *ima = ED_space_image(sima);
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
|
||||
Scene *scene;
|
||||
RenderResult *rr = NULL;
|
||||
bool ok = false;
|
||||
|
||||
WM_cursor_wait(1);
|
||||
|
||||
if (ibuf) {
|
||||
ImBuf *colormanaged_ibuf = NULL;
|
||||
const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id);
|
||||
@@ -2036,11 +2117,49 @@ cleanup:
|
||||
BKE_image_release_renderresult(scene, ima);
|
||||
}
|
||||
|
||||
WM_cursor_wait(0);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath)
|
||||
{
|
||||
Image *ima = ED_space_image(sima);
|
||||
|
||||
if (ima->source == IMA_SRC_TILED) {
|
||||
if (BLI_stringdec(simopts->filepath, NULL, NULL, NULL) != 1001) {
|
||||
BKE_reportf(op->reports, RPT_ERROR,
|
||||
"When saving a tiled image, the path '%s' must contain the UDIM tag 1001", simopts->filepath);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WM_cursor_wait(1);
|
||||
|
||||
if (!save_image_single(C, sima, op, simopts, do_newpath, 0)) {
|
||||
WM_cursor_wait(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ima->source == IMA_SRC_TILED) {
|
||||
char filepath[FILE_MAX];
|
||||
BLI_strncpy(filepath, simopts->filepath, sizeof(filepath));
|
||||
LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) {
|
||||
if (tile->tile_number == 0)
|
||||
continue;
|
||||
|
||||
char head[FILE_MAX], tail[FILE_MAX];
|
||||
unsigned short numlen;
|
||||
BLI_stringdec(filepath, head, tail, &numlen);
|
||||
BLI_stringenc(simopts->filepath, head, tail, numlen, 1001 + tile->tile_number);
|
||||
|
||||
save_image_single(C, sima, op, simopts, do_newpath, tile->tile_number);
|
||||
}
|
||||
BLI_strncpy(simopts->filepath, filepath, sizeof(simopts->filepath));
|
||||
}
|
||||
|
||||
WM_cursor_wait(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void image_save_as_free(wmOperator *op)
|
||||
{
|
||||
if (op->customdata) {
|
||||
@@ -2258,7 +2377,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op)
|
||||
if (sima->image == NULL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (sima->image->source != IMA_SRC_SEQUENCE) {
|
||||
if (ELEM(sima->image->source, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Can only save sequence on image sequences");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
@@ -2441,11 +2560,12 @@ static int image_new_exec(bContext *C, wmOperator *op)
|
||||
RNA_float_get_array(op->ptr, "color", color);
|
||||
alpha = RNA_boolean_get(op->ptr, "alpha");
|
||||
stereo3d = RNA_boolean_get(op->ptr, "use_stereo_3d");
|
||||
bool tiled = RNA_boolean_get(op->ptr, "tiled");
|
||||
|
||||
if (!alpha)
|
||||
color[3] = 1.0f;
|
||||
|
||||
ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d);
|
||||
ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d, tiled);
|
||||
|
||||
if (!ima) {
|
||||
image_new_free(op);
|
||||
@@ -2529,6 +2649,9 @@ static void image_new_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
uiItemL(col[0], "", ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE);
|
||||
|
||||
uiItemL(col[0], "", ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "tiled", 0, NULL, ICON_NONE);
|
||||
|
||||
#if 0
|
||||
if (is_multiview) {
|
||||
uiItemL(col[0], "", ICON_NONE);
|
||||
@@ -2577,6 +2700,8 @@ void IMAGE_OT_new(wmOperatorType *ot)
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
prop = RNA_def_boolean(ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||
prop = RNA_def_boolean(ot->srna, "tiled", 0, "Tiled", "Create a tiled image");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
#undef IMA_DEF_NAME
|
||||
@@ -2704,7 +2829,7 @@ static bool image_pack_test(bContext *C, wmOperator *op)
|
||||
if (!as_png && BKE_image_has_packedfile(ima))
|
||||
return 0;
|
||||
|
||||
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
|
||||
return 0;
|
||||
}
|
||||
@@ -2805,7 +2930,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
|
||||
if (!ima || !BKE_image_has_packedfile(ima))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
@@ -2833,7 +2958,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
|
||||
if (!ima || !BKE_image_has_packedfile(ima))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
|
||||
if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
@@ -2903,9 +3028,12 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
|
||||
/* Returns color in linear space, matching ED_space_node_color_sample(). */
|
||||
bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], float r_col[3])
|
||||
{
|
||||
float uv[2];
|
||||
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &uv[0], &uv[1]);
|
||||
int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL);
|
||||
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
float fx, fy;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
|
||||
bool ret = false;
|
||||
|
||||
if (ibuf == NULL) {
|
||||
@@ -2913,12 +3041,10 @@ bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], flo
|
||||
return false;
|
||||
}
|
||||
|
||||
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fx, &fy);
|
||||
|
||||
if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
|
||||
if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 1.0f && uv[1] < 1.0f) {
|
||||
const float *fp;
|
||||
unsigned char *cp;
|
||||
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
|
||||
int x = (int)(uv[0] * ibuf->x), y = (int)(uv[1] * ibuf->y);
|
||||
|
||||
CLAMP(x, 0, ibuf->x - 1);
|
||||
CLAMP(y, 0, ibuf->y - 1);
|
||||
@@ -2944,10 +3070,15 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
Image *image = ED_space_image(sima);
|
||||
|
||||
float uv[2];
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &uv[0], &uv[1]);
|
||||
int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL);
|
||||
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
|
||||
ImageSampleInfo *info = op->customdata;
|
||||
float fx, fy;
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
CurveMapping *curve_mapping = scene->view_settings.curve_mapping;
|
||||
|
||||
@@ -2957,13 +3088,10 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
|
||||
return;
|
||||
}
|
||||
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
|
||||
|
||||
if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
|
||||
if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 1.0f && uv[1] < 1.0f) {
|
||||
const float *fp;
|
||||
unsigned char *cp;
|
||||
int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
|
||||
Image *image = ED_space_image(sima);
|
||||
int x = (int)(uv[0] * ibuf->x), y = (int)(uv[1] * ibuf->y);
|
||||
|
||||
CLAMP(x, 0, ibuf->x - 1);
|
||||
CLAMP(y, 0, ibuf->y - 1);
|
||||
@@ -3171,11 +3299,28 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
|
||||
int x_end = RNA_int_get(op->ptr, "xend");
|
||||
int y_end = RNA_int_get(op->ptr, "yend");
|
||||
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
Histogram *hist = &sima->sample_line_hist;
|
||||
|
||||
float x1f, y1f, x2f, y2f;
|
||||
UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &x1f, &y1f);
|
||||
UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &x2f, &y2f);
|
||||
|
||||
/* If the image has tiles, shift the positions accordingly. */
|
||||
Image *image = ED_space_image(sima);
|
||||
int tile = 0, ix = 0, iy = 0;
|
||||
if (image && image->source == IMA_SRC_TILED) {
|
||||
ix = (int) x1f;
|
||||
iy = (int) y1f;
|
||||
CLAMP(ix, 0, 9);
|
||||
|
||||
x1f -= ix;
|
||||
x2f -= ix;
|
||||
y1f -= iy;
|
||||
y2f -= iy;
|
||||
tile = 10*iy + ix;
|
||||
}
|
||||
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
|
||||
Histogram *hist = &sima->sample_line_hist;
|
||||
|
||||
if (ibuf == NULL) {
|
||||
ED_space_image_release_buffer(sima, ibuf, lock);
|
||||
@@ -3187,13 +3332,12 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &x1f, &y1f);
|
||||
UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &x2f, &y2f);
|
||||
|
||||
hist->co[0][0] = x1f;
|
||||
hist->co[0][1] = y1f;
|
||||
hist->co[1][0] = x2f;
|
||||
hist->co[1][1] = y2f;
|
||||
hist->draw_offset[0] = ix;
|
||||
hist->draw_offset[1] = iy;
|
||||
|
||||
/* enable line drawing */
|
||||
hist->flag |= HISTO_FLAG_SAMPLELINE;
|
||||
@@ -3807,3 +3951,227 @@ void IMAGE_OT_clear_render_border(wmOperatorType *ot)
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ********************* Add tile operator ****************** */
|
||||
|
||||
static bool add_tile_poll(bContext *C)
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = CTX_data_edit_image(C);
|
||||
|
||||
return (ima && ima->source == IMA_SRC_TILED && (BKE_image_get_tile(ima, sima->curtile) == NULL));
|
||||
}
|
||||
|
||||
static int add_tile_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = ED_space_image(sima);
|
||||
|
||||
if (BKE_image_add_tile(ima, sima->curtile, NULL) == NULL)
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void IMAGE_OT_add_tile(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Add tile";
|
||||
ot->description = "Adds a tile to the image";
|
||||
ot->idname = "IMAGE_OT_add_tile";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = add_tile_poll;
|
||||
ot->exec = add_tile_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ********************* Remove tile operator ****************** */
|
||||
|
||||
static bool remove_tile_poll(bContext *C)
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = CTX_data_edit_image(C);
|
||||
|
||||
return (ima && ima->source == IMA_SRC_TILED && BKE_image_get_tile(ima, sima->curtile));
|
||||
}
|
||||
|
||||
static int remove_tile_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = ED_space_image(sima);
|
||||
|
||||
ImageTile *tile = BKE_image_get_tile(ima, sima->curtile);
|
||||
if (!BKE_image_remove_tile(ima, tile))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void IMAGE_OT_remove_tile(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Remove tile";
|
||||
ot->description = "Removes a tile from the image";
|
||||
ot->idname = "IMAGE_OT_remove_tile";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = remove_tile_poll;
|
||||
ot->exec = remove_tile_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ********************* Fill tile operator ****************** */
|
||||
|
||||
static bool fill_tile_poll(bContext *C)
|
||||
{
|
||||
Image *ima = CTX_data_edit_image(C);
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
|
||||
return (ima && ima->source == IMA_SRC_TILED && BKE_image_get_tile(ima, sima->curtile));
|
||||
}
|
||||
|
||||
static int fill_tile_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = ED_space_image(sima);
|
||||
|
||||
float color[4];
|
||||
RNA_float_get_array(op->ptr, "color", color);
|
||||
int gen_type = RNA_enum_get(op->ptr, "generated_type");
|
||||
int width = RNA_int_get(op->ptr, "width");
|
||||
int height = RNA_int_get(op->ptr, "height");
|
||||
|
||||
ImageTile *tile = BKE_image_get_tile(ima, sima->curtile);
|
||||
if (!BKE_image_fill_tile(ima, tile, width, height, color, gen_type))
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int fill_tile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = ED_space_image(sima);
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
|
||||
if (ibuf) {
|
||||
RNA_int_set(op->ptr, "width", ibuf->x);
|
||||
RNA_int_set(op->ptr, "height", ibuf->y);
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
}
|
||||
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
|
||||
}
|
||||
|
||||
static void fill_tile_draw(bContext *UNUSED(C), wmOperator *op)
|
||||
{
|
||||
uiLayout *split, *col[2];
|
||||
uiLayout *layout = op->layout;
|
||||
PointerRNA ptr;
|
||||
|
||||
RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
|
||||
|
||||
/* copy of WM_operator_props_dialog_popup() layout */
|
||||
|
||||
split = uiLayoutSplit(layout, 0.5f, false);
|
||||
col[0] = uiLayoutColumn(split, false);
|
||||
col[1] = uiLayoutColumn(split, false);
|
||||
|
||||
uiItemL(col[0], IFACE_("Color"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "color", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], IFACE_("Width"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "width", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], IFACE_("Height"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "height", 0, "", ICON_NONE);
|
||||
|
||||
uiItemL(col[0], IFACE_("Generated Type"), ICON_NONE);
|
||||
uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE);
|
||||
}
|
||||
|
||||
void IMAGE_OT_fill_tile(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Fill tile";
|
||||
ot->description = "Fill the current tile with a generated image";
|
||||
ot->idname = "IMAGE_OT_fill_tile";
|
||||
|
||||
/* api callbacks */
|
||||
ot->poll = fill_tile_poll;
|
||||
ot->exec = fill_tile_exec;
|
||||
ot->invoke = fill_tile_invoke;
|
||||
ot->ui = fill_tile_draw;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
PropertyRNA *prop;
|
||||
static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
prop = RNA_def_float_color(ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
|
||||
RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
|
||||
RNA_def_property_float_array_default(prop, default_color);
|
||||
RNA_def_enum(ot->srna, "generated_type", rna_enum_image_generated_type_items, IMA_GENTYPE_BLANK,
|
||||
"Generated Type", "Fill the image with a grid for UV map testing");
|
||||
prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
|
||||
RNA_def_property_subtype(prop, PROP_PIXEL);
|
||||
prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
|
||||
RNA_def_property_subtype(prop, PROP_PIXEL);
|
||||
}
|
||||
|
||||
/* ********************* Select tile operator ****************** */
|
||||
|
||||
static bool image_select_tile_poll(bContext *C)
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Image *ima = CTX_data_edit_image(C);
|
||||
|
||||
if (ima) {
|
||||
return (ima->source == IMA_SRC_TILED);
|
||||
}
|
||||
else {
|
||||
return (sima->tile_grid_shape[0] > 1) || (sima->tile_grid_shape[1] > 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int image_select_tile_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
|
||||
{
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
|
||||
float uv[2];
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &uv[0], &uv[1]);
|
||||
|
||||
if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 10.0f) {
|
||||
int tx = (int) uv[0];
|
||||
int ty = (int) uv[1];
|
||||
|
||||
sima->curtile = 10*ty + tx;
|
||||
|
||||
WM_event_add_notifier(C, NC_WINDOW, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void IMAGE_OT_select_tile(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Select tile";
|
||||
ot->idname = "IMAGE_OT_select_tile";
|
||||
ot->description = "Use mouse to select a tile of the image";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = image_select_tile_invoke;
|
||||
ot->poll = image_select_tile_poll;
|
||||
}
|
@@ -183,6 +183,9 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce
|
||||
scopes_new(&simage->scopes);
|
||||
simage->sample_line_hist.height = 100;
|
||||
|
||||
simage->tile_grid_shape[0] = 1;
|
||||
simage->tile_grid_shape[1] = 1;
|
||||
|
||||
/* header */
|
||||
ar = MEM_callocN(sizeof(ARegion), "header for image");
|
||||
|
||||
@@ -289,6 +292,11 @@ static void image_operatortypes(void)
|
||||
WM_operatortype_append(IMAGE_OT_read_viewlayers);
|
||||
WM_operatortype_append(IMAGE_OT_render_border);
|
||||
WM_operatortype_append(IMAGE_OT_clear_render_border);
|
||||
|
||||
WM_operatortype_append(IMAGE_OT_add_tile);
|
||||
WM_operatortype_append(IMAGE_OT_remove_tile);
|
||||
WM_operatortype_append(IMAGE_OT_fill_tile);
|
||||
WM_operatortype_append(IMAGE_OT_select_tile);
|
||||
}
|
||||
|
||||
static void image_keymap(struct wmKeyConfig *keyconf)
|
||||
@@ -355,6 +363,7 @@ static void image_keymap(struct wmKeyConfig *keyconf)
|
||||
WM_keymap_add_item(keymap, "IMAGE_OT_sample", ACTIONMOUSE, KM_PRESS, 0, 0);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "IMAGE_OT_curves_point_set", ACTIONMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "point", 0);
|
||||
RNA_enum_set(WM_keymap_add_item(keymap, "IMAGE_OT_curves_point_set", ACTIONMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "point", 1);
|
||||
WM_keymap_add_item(keymap, "IMAGE_OT_select_tile", ACTIONMOUSE, KM_PRESS, KM_ALT, 0);
|
||||
|
||||
/* toggle editmode is handy to have while UV unwrapping */
|
||||
kmi = WM_keymap_add_item(keymap, "OBJECT_OT_mode_set", TABKEY, KM_PRESS, 0, 0);
|
||||
@@ -929,7 +938,8 @@ static void image_tools_region_draw(const bContext *C, ARegion *ar)
|
||||
SpaceImage *sima = CTX_wm_space_image(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
void *lock;
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
/* TODO(lukas): Support tiles in scopes? */
|
||||
ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
/* XXX performance regression if name of scopes category changes! */
|
||||
PanelCategoryStack *category = UI_panel_category_active_find(ar, "Scopes");
|
||||
|
||||
|
@@ -220,7 +220,7 @@ GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
|
||||
GPUNodeLink *GPU_uniform(float *num);
|
||||
GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data);
|
||||
GPUNodeLink *GPU_uniform_buffer(float *num, GPUType gputype);
|
||||
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
|
||||
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data, int tile);
|
||||
GPUNodeLink *GPU_cube_map(struct Image *ima, struct ImageUser *iuser, bool is_data);
|
||||
GPUNodeLink *GPU_image_preview(struct PreviewImage *prv);
|
||||
GPUNodeLink *GPU_texture(int size, float *pixels);
|
||||
|
@@ -515,17 +515,19 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
|
||||
}
|
||||
|
||||
/* assign only one texid per buffer to avoid sampling the same texture twice */
|
||||
static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key)
|
||||
static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key1, int key2)
|
||||
{
|
||||
if (BLI_ghash_haskey(bindhash, key)) {
|
||||
GHashPair pair = {key1, SET_INT_IN_POINTER(key2 << 16)};
|
||||
if (BLI_ghash_haskey(bindhash, &pair)) {
|
||||
/* Reuse existing texid */
|
||||
input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, key));
|
||||
input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, &pair));
|
||||
}
|
||||
else {
|
||||
/* Allocate new texid */
|
||||
input->texid = *texid;
|
||||
(*texid)++;
|
||||
input->bindtex = true;
|
||||
void *key = BLI_ghashutil_pairalloc(key1, SET_INT_IN_POINTER(key2));
|
||||
BLI_ghash_insert(bindhash, key, SET_INT_IN_POINTER(input->texid));
|
||||
}
|
||||
}
|
||||
@@ -538,7 +540,7 @@ static void codegen_set_unique_ids(ListBase *nodes)
|
||||
GPUOutput *output;
|
||||
int id = 1, texid = 0;
|
||||
|
||||
bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
|
||||
bindhash = BLI_ghash_pair_new("codegen_set_unique_ids1 gh");
|
||||
definehash = BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
|
||||
|
||||
for (node = nodes->first; node; node = node->next) {
|
||||
@@ -556,19 +558,19 @@ static void codegen_set_unique_ids(ListBase *nodes)
|
||||
* the same texture twice */
|
||||
if (input->link) {
|
||||
/* input is texture from buffer */
|
||||
codegen_set_texid(bindhash, input, &texid, input->link);
|
||||
codegen_set_texid(bindhash, input, &texid, input->link, 0);
|
||||
}
|
||||
else if (input->ima) {
|
||||
/* input is texture from image */
|
||||
codegen_set_texid(bindhash, input, &texid, input->ima);
|
||||
codegen_set_texid(bindhash, input, &texid, input->ima, input->image_tile);
|
||||
}
|
||||
else if (input->prv) {
|
||||
/* input is texture from preview render */
|
||||
codegen_set_texid(bindhash, input, &texid, input->prv);
|
||||
codegen_set_texid(bindhash, input, &texid, input->prv, 0);
|
||||
}
|
||||
else if (input->tex) {
|
||||
/* input is user created texture, check tex pointer */
|
||||
codegen_set_texid(bindhash, input, &texid, input->tex);
|
||||
codegen_set_texid(bindhash, input, &texid, input->tex, 0);
|
||||
}
|
||||
|
||||
/* make sure this pixel is defined exactly once */
|
||||
@@ -594,7 +596,7 @@ static void codegen_set_unique_ids(ListBase *nodes)
|
||||
output->id = id++;
|
||||
}
|
||||
|
||||
BLI_ghash_free(bindhash, NULL, NULL);
|
||||
BLI_ghash_free(bindhash, BLI_ghashutil_pairfree, NULL);
|
||||
BLI_ghash_free(definehash, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -1355,6 +1357,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
|
||||
input->ima = link->ptr1;
|
||||
input->iuser = link->ptr2;
|
||||
input->image_isdata = link->image_isdata;
|
||||
input->image_tile = link->val1;
|
||||
input->textarget = GL_TEXTURE_2D;
|
||||
input->textype = GPU_TEX2D;
|
||||
}
|
||||
@@ -1652,13 +1655,14 @@ GPUNodeLink *GPU_uniform_buffer(float *num, GPUType gputype)
|
||||
return link;
|
||||
}
|
||||
|
||||
GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
|
||||
GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data, int tile)
|
||||
{
|
||||
GPUNodeLink *link = GPU_node_link_create();
|
||||
|
||||
link->image = GPU_NODE_LINK_IMAGE_BLENDER;
|
||||
link->ptr1 = ima;
|
||||
link->ptr2 = iuser;
|
||||
link->val1 = tile;
|
||||
link->image_isdata = is_data;
|
||||
|
||||
return link;
|
||||
|
@@ -93,6 +93,7 @@ struct GPUNodeLink {
|
||||
int texturesize;
|
||||
|
||||
void *ptr1, *ptr2;
|
||||
int val1;
|
||||
|
||||
bool dynamic;
|
||||
GPUDynamicType dynamictype;
|
||||
@@ -137,6 +138,7 @@ typedef struct GPUInput {
|
||||
|
||||
struct Image *ima; /* image */
|
||||
struct ImageUser *iuser; /* image user */
|
||||
int image_tile; /* image tile */
|
||||
struct PreviewImage *prv; /* preview images & icons */
|
||||
bool image_isdata; /* image does not contain color data */
|
||||
float *dynamicvec; /* vector data in case it is dynamic */
|
||||
|
@@ -224,16 +224,6 @@ float GPU_get_anisotropic(void)
|
||||
|
||||
/* Set OpenGL state for an MTFace */
|
||||
|
||||
static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget)
|
||||
{
|
||||
if (textarget == GL_TEXTURE_2D)
|
||||
return &ima->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
else if (textarget == GL_TEXTURE_CUBE_MAP)
|
||||
return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct VerifyThreadData {
|
||||
ImBuf *ibuf;
|
||||
float *srgb_frect;
|
||||
@@ -301,18 +291,22 @@ GPUTexture *GPU_texture_from_blender(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int gputex_type = (textarget == GL_TEXTURE_CUBE_MAP)? TEXTARGET_TEXTURE_CUBE_MAP : TEXTARGET_TEXTURE_2D;
|
||||
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
|
||||
|
||||
/* Test if we already have a texture. */
|
||||
GPUTexture **tex = gpu_get_image_gputexture(ima, textarget);
|
||||
if (*tex) {
|
||||
return *tex;
|
||||
GPUTexture *tex = tile->gputexture[gputex_type];
|
||||
if (tex) {
|
||||
return tex;
|
||||
}
|
||||
|
||||
/* Check if we have a valid image. If not, we return a dummy
|
||||
* texture with zero bindcode so we don't keep trying. */
|
||||
unsigned int bindcode = 0;
|
||||
if (ima->ok == 0) {
|
||||
*tex = GPU_texture_from_bindcode(textarget, bindcode);
|
||||
return *tex;
|
||||
if (tile->ok == 0) {
|
||||
tex = GPU_texture_from_bindcode(textarget, bindcode);
|
||||
tile->gputexture[gputex_type] = tex;
|
||||
return tex;
|
||||
}
|
||||
|
||||
/* currently, tpage refresh is used by ima sequences */
|
||||
@@ -324,8 +318,9 @@ GPUTexture *GPU_texture_from_blender(
|
||||
/* check if we have a valid image buffer */
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
|
||||
if (ibuf == NULL) {
|
||||
*tex = GPU_texture_from_bindcode(textarget, bindcode);
|
||||
return *tex;
|
||||
tex = GPU_texture_from_bindcode(textarget, bindcode);
|
||||
tile->gputexture[gputex_type] = tex;
|
||||
return tex;
|
||||
}
|
||||
|
||||
/* flag to determine whether deep format is used */
|
||||
@@ -393,8 +388,9 @@ GPUTexture *GPU_texture_from_blender(
|
||||
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
|
||||
*tex = GPU_texture_from_bindcode(textarget, bindcode);
|
||||
return *tex;
|
||||
tex = GPU_texture_from_bindcode(textarget, bindcode);
|
||||
tile->gputexture[gputex_type] = tex;
|
||||
return tex;
|
||||
}
|
||||
|
||||
static void **gpu_gen_cube_map(unsigned int *rect, float *frect, int rectw, int recth, bool use_high_bit_depth)
|
||||
@@ -703,44 +699,43 @@ void GPU_paint_set_mipmap(Main *bmain, bool mipmap)
|
||||
|
||||
if (mipmap) {
|
||||
for (Image *ima = bmain->image.first; ima; ima = ima->id.next) {
|
||||
if (BKE_image_has_opengl_texture(ima)) {
|
||||
bool has_gputexture = false;
|
||||
LISTBASE_FOREACH(ImageTile *, tile, &ima->tiles) {
|
||||
if (ima->tpageflag & IMA_MIPMAP_COMPLETE) {
|
||||
if (ima->gputexture[TEXTARGET_TEXTURE_2D]) {
|
||||
GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
|
||||
GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
if (tex) {
|
||||
GPU_texture_bind(tex, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
|
||||
GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
}
|
||||
else
|
||||
GPU_free_image(ima);
|
||||
}
|
||||
else
|
||||
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
|
||||
if (!has_gputexture) GPU_free_image(ima);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
for (Image *ima = bmain->image.first; ima; ima = ima->id.next) {
|
||||
if (BKE_image_has_opengl_texture(ima)) {
|
||||
if (ima->gputexture[TEXTARGET_TEXTURE_2D]) {
|
||||
GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
|
||||
LISTBASE_FOREACH(ImageTile *, tile, &ima->tiles) {
|
||||
GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
if (tex) {
|
||||
GPU_texture_bind(tex, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
|
||||
GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
}
|
||||
else
|
||||
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* check if image has been downscaled and do scaled partial update */
|
||||
static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h)
|
||||
static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, ImageTile *tile, float *frect, int x, int y, int w, int h)
|
||||
{
|
||||
if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) {
|
||||
GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
|
||||
int x_limit = smaller_power_of_2_limit(ibuf->x);
|
||||
int y_limit = smaller_power_of_2_limit(ibuf->y);
|
||||
|
||||
@@ -760,7 +755,7 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
|
||||
if (rectw + x > x_limit) rectw--;
|
||||
if (recth + y > y_limit) recth--;
|
||||
|
||||
GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
|
||||
GPU_texture_bind(tex, 0);
|
||||
|
||||
/* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */
|
||||
if (frect) {
|
||||
@@ -802,7 +797,7 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
|
||||
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
|
||||
}
|
||||
|
||||
GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
|
||||
GPU_texture_unbind(tex);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -813,9 +808,11 @@ static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
|
||||
void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
|
||||
{
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
|
||||
ImageTile *tile = BKE_image_get_tile_from_iuser(ima, iuser);
|
||||
|
||||
GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
if ((!GTS.gpu_mipmap && GPU_get_mipmap()) ||
|
||||
(ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) ||
|
||||
(tex == NULL) ||
|
||||
(ibuf == NULL) ||
|
||||
(w == 0) || (h == 0))
|
||||
{
|
||||
@@ -833,13 +830,13 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
|
||||
bool is_data = (ima->tpageflag & IMA_GLBIND_IS_DATA) != 0;
|
||||
IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data);
|
||||
|
||||
if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) {
|
||||
if (gpu_check_scaled_image(ibuf, ima, tile, buffer, x, y, w, h)) {
|
||||
MEM_freeN(buffer);
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
|
||||
GPU_texture_bind(tex, 0);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer);
|
||||
|
||||
MEM_freeN(buffer);
|
||||
@@ -853,18 +850,18 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
|
||||
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
|
||||
}
|
||||
|
||||
GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
|
||||
GPU_texture_unbind(tex);
|
||||
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) {
|
||||
if (gpu_check_scaled_image(ibuf, ima, tile, NULL, x, y, w, h)) {
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0);
|
||||
GPU_texture_bind(tex, 0);
|
||||
|
||||
glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length);
|
||||
glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels);
|
||||
@@ -890,7 +887,7 @@ void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, i
|
||||
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
|
||||
}
|
||||
|
||||
GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]);
|
||||
GPU_texture_unbind(tex);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(ima, ibuf, NULL);
|
||||
@@ -1077,11 +1074,14 @@ void GPU_free_image(Image *ima)
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < TEXTARGET_COUNT; i++) {
|
||||
/* free glsl image binding */
|
||||
if (ima->gputexture[i]) {
|
||||
GPU_texture_free(ima->gputexture[i]);
|
||||
ima->gputexture[i] = NULL;
|
||||
LISTBASE_FOREACH(ImageTile *, tile, &ima->tiles) {
|
||||
for (int i = 0; i < TEXTARGET_COUNT; i++) {
|
||||
/* free glsl image binding */
|
||||
GPUTexture *tex = tile->gputexture[i];
|
||||
if (tex) {
|
||||
GPU_texture_free(tex);
|
||||
tile->gputexture[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1879,6 +1879,67 @@ void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alph
|
||||
node_tex_image_cubic(co, ima, color, alpha);
|
||||
}
|
||||
|
||||
void node_tex_image_tiled_map(vec3 co, out vec4 color, out vec3 map)
|
||||
{
|
||||
float tx = floor(co.x);
|
||||
float ty = floor(co.y);
|
||||
|
||||
if (tx < 0 || ty < 0 || tx >= 10)
|
||||
map = vec3(0, 0, -1);
|
||||
else
|
||||
map = vec3(co.x - tx, co.y - ty, 10*ty + tx);
|
||||
|
||||
color = vec4(1.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
void node_tex_image_tile_linear(vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
|
||||
{
|
||||
if (map.z == tile_id) {
|
||||
vec3 co = map.xyy;
|
||||
node_tex_image_linear(co, ima, color, alpha);
|
||||
}
|
||||
else {
|
||||
color = in_color;
|
||||
alpha = color.a;
|
||||
}
|
||||
}
|
||||
|
||||
void node_tex_image_tile_nearest(vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
|
||||
{
|
||||
if (map.z == tile_id) {
|
||||
vec3 co = map.xyy;
|
||||
node_tex_image_nearest(co, ima, color, alpha);
|
||||
}
|
||||
else {
|
||||
color = in_color;
|
||||
alpha = color.a;
|
||||
}
|
||||
}
|
||||
|
||||
void node_tex_image_tile_cubic(vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
|
||||
{
|
||||
if (map.z == tile_id) {
|
||||
vec3 co = map.xyy;
|
||||
node_tex_image_cubic(co, ima, color, alpha);
|
||||
}
|
||||
else {
|
||||
color = in_color;
|
||||
alpha = color.a;
|
||||
}
|
||||
}
|
||||
|
||||
void node_tex_image_tile_smart(vec3 map, float tile_id, sampler2D ima, vec4 in_color, out vec4 color, out float alpha)
|
||||
{
|
||||
if (map.z == tile_id) {
|
||||
vec3 co = map.xyy;
|
||||
node_tex_image_smart(co, ima, color, alpha);
|
||||
}
|
||||
else {
|
||||
color = in_color;
|
||||
alpha = color.a;
|
||||
}
|
||||
}
|
||||
|
||||
void tex_box_sample_linear(vec3 texco,
|
||||
vec3 N,
|
||||
sampler2D ima,
|
||||
|
@@ -60,6 +60,7 @@ void IMB_moviecache_set_priority_callback(struct MovieCache *cache, MovieCacheGe
|
||||
void IMB_moviecache_put(struct MovieCache *cache, void *userkey, struct ImBuf *ibuf);
|
||||
bool IMB_moviecache_put_if_possible(struct MovieCache *cache, void *userkey, struct ImBuf *ibuf);
|
||||
struct ImBuf *IMB_moviecache_get(struct MovieCache *cache, void *userkey);
|
||||
void IMB_moviecache_remove(struct MovieCache *cache, void *userkey);
|
||||
bool IMB_moviecache_has_frame(struct MovieCache *cache, void *userkey);
|
||||
void IMB_moviecache_free(struct MovieCache *cache);
|
||||
|
||||
|
@@ -415,6 +415,14 @@ bool IMB_moviecache_put_if_possible(MovieCache *cache, void *userkey, ImBuf *ibu
|
||||
return result;
|
||||
}
|
||||
|
||||
void IMB_moviecache_remove(MovieCache *cache, void *userkey)
|
||||
{
|
||||
MovieCacheKey key;
|
||||
key.cache_owner = cache;
|
||||
key.userkey = userkey;
|
||||
BLI_ghash_remove(cache->hash, &key, moviecache_keyfree, moviecache_valfree);
|
||||
}
|
||||
|
||||
ImBuf *IMB_moviecache_get(MovieCache *cache, void *userkey)
|
||||
{
|
||||
MovieCacheKey key;
|
||||
|
@@ -132,6 +132,7 @@ typedef struct Histogram {
|
||||
/* sample line only */
|
||||
/* image coords src -> dst */
|
||||
float co[2][2];
|
||||
float draw_offset[2];
|
||||
} Histogram;
|
||||
|
||||
|
||||
|
@@ -58,6 +58,9 @@ typedef struct ImageUser {
|
||||
short pass;
|
||||
short pad;
|
||||
|
||||
int tile; /* current tile (for internal use) */
|
||||
int pad2;
|
||||
|
||||
short multi_index, view, layer; /* listbase indices, for menu browsing or retrieve buffer */
|
||||
short flag;
|
||||
} ImageUser;
|
||||
@@ -85,6 +88,21 @@ typedef struct RenderSlot {
|
||||
struct RenderResult *render;
|
||||
} RenderSlot;
|
||||
|
||||
enum {
|
||||
TEXTARGET_TEXTURE_2D = 0,
|
||||
TEXTARGET_TEXTURE_CUBE_MAP = 1,
|
||||
TEXTARGET_COUNT = 2
|
||||
};
|
||||
|
||||
typedef struct ImageTile {
|
||||
struct ImageTile *next, *prev;
|
||||
struct GPUTexture *gputexture[2]; /* TEXTARGET_COUNT */
|
||||
char ok;
|
||||
char pad[3];
|
||||
int tile_number;
|
||||
char label[64];
|
||||
} ImageTile;
|
||||
|
||||
/* iuser->flag */
|
||||
#define IMA_ANIM_ALWAYS 1
|
||||
#define IMA_ANIM_REFRESHED 2
|
||||
@@ -92,11 +110,6 @@ typedef struct RenderSlot {
|
||||
#define IMA_NEED_FRAME_RECALC 8
|
||||
#define IMA_SHOW_STEREO 16
|
||||
|
||||
enum {
|
||||
TEXTARGET_TEXTURE_2D = 0,
|
||||
TEXTARGET_TEXTURE_CUBE_MAP = 1,
|
||||
TEXTARGET_COUNT = 2
|
||||
};
|
||||
|
||||
typedef struct Image {
|
||||
ID id;
|
||||
@@ -104,7 +117,6 @@ typedef struct Image {
|
||||
char name[1024]; /* file path, 1024 = FILE_MAX */
|
||||
|
||||
struct MovieCache *cache; /* not written in file */
|
||||
struct GPUTexture *gputexture[2]; /* not written in file 2 = TEXTARGET_COUNT */
|
||||
|
||||
/* sources from: */
|
||||
ListBase anims;
|
||||
@@ -119,16 +131,17 @@ typedef struct Image {
|
||||
|
||||
/* texture page */
|
||||
short tpageflag;
|
||||
short pad2;
|
||||
unsigned int pad3;
|
||||
short pad3;
|
||||
|
||||
int lastused;
|
||||
|
||||
ListBase tiles;
|
||||
|
||||
struct PackedFile *packedfile DNA_DEPRECATED; /* deprecated */
|
||||
struct ListBase packedfiles;
|
||||
struct PreviewImage *preview;
|
||||
|
||||
int lastused;
|
||||
short ok;
|
||||
short pad4[3];
|
||||
int pad2;
|
||||
|
||||
/* for generated images */
|
||||
int gen_x, gen_y;
|
||||
|
@@ -922,6 +922,8 @@ typedef struct SpaceImage {
|
||||
|
||||
int flag;
|
||||
|
||||
int tile_grid_shape[2];
|
||||
|
||||
MaskSpaceInfo mask_info;
|
||||
} SpaceImage;
|
||||
|
||||
|
@@ -59,6 +59,7 @@ static const EnumPropertyItem image_source_items[] = {
|
||||
{IMA_SRC_MOVIE, "MOVIE", 0, "Movie", "Movie file"},
|
||||
{IMA_SRC_GENERATED, "GENERATED", 0, "Generated", "Generated image"},
|
||||
{IMA_SRC_VIEWER, "VIEWER", 0, "Viewer", "Compositing node viewer"},
|
||||
{IMA_SRC_TILED, "TILED", 0, "Tiled", "Tiled image texture"},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -190,6 +191,7 @@ static const EnumPropertyItem *rna_Image_source_itemf(bContext *UNUSED(C), Point
|
||||
RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_SEQUENCE);
|
||||
RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_MOVIE);
|
||||
RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_GENERATED);
|
||||
RNA_enum_items_add_value(&item, &totitem, image_source_items, IMA_SRC_TILED);
|
||||
}
|
||||
|
||||
RNA_enum_item_end(&item, &totitem);
|
||||
@@ -279,13 +281,6 @@ static void rna_Image_resolution_set(PointerRNA *ptr, const float *values)
|
||||
BKE_image_release_ibuf(im, ibuf, lock);
|
||||
}
|
||||
|
||||
static int rna_Image_bindcode_get(PointerRNA *ptr)
|
||||
{
|
||||
Image *ima = (Image *)ptr->data;
|
||||
GPUTexture *tex = ima->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
return (tex) ? GPU_texture_opengl_bindcode(tex) : 0;
|
||||
}
|
||||
|
||||
static int rna_Image_depth_get(PointerRNA *ptr)
|
||||
{
|
||||
Image *im = (Image *)ptr->data;
|
||||
@@ -491,6 +486,23 @@ static void rna_render_slots_active_index_range(PointerRNA *ptr, int *min, int *
|
||||
*max = max_ii(0, BLI_listbase_count(&image->renderslots) - 1);
|
||||
}
|
||||
|
||||
static ImageTile *rna_ImageTile_new(Image *image, int tile_number, const char *label)
|
||||
{
|
||||
ImageTile *tile = BKE_image_add_tile(image, tile_number, label);
|
||||
|
||||
WM_main_add_notifier(NC_IMAGE | ND_DRAW, NULL);
|
||||
|
||||
return tile;
|
||||
}
|
||||
|
||||
static void rna_ImageTile_remove(ID *id, ImageTile *tile)
|
||||
{
|
||||
Image *image = (Image *)id;
|
||||
BKE_image_remove_tile(image, tile);
|
||||
|
||||
WM_main_add_notifier(NC_IMAGE | ND_DRAW, NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_imageuser(BlenderRNA *brna)
|
||||
@@ -555,6 +567,11 @@ static void rna_def_imageuser(BlenderRNA *brna)
|
||||
RNA_def_property_int_sdna(prop, NULL, "view");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
|
||||
RNA_def_property_ui_text(prop, "View", "View in multilayer image");
|
||||
|
||||
prop = RNA_def_property(srna, "tile", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_sdna(prop, NULL, "tile");
|
||||
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
|
||||
RNA_def_property_ui_text(prop, "Tile", "Tile in tiled image");
|
||||
}
|
||||
|
||||
/* image.packed_files */
|
||||
@@ -632,6 +649,56 @@ static void rna_def_render_slots(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void rna_def_image_tile(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *prop;
|
||||
srna = RNA_def_struct(brna, "ImageTile", NULL);
|
||||
RNA_def_struct_ui_text(srna, "Image Tile", "Properties of the image tile");
|
||||
|
||||
prop = RNA_def_property(srna, "label", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "label");
|
||||
RNA_def_property_ui_text(prop, "Label", "Tile label");
|
||||
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "tile_number", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "tile_number");
|
||||
RNA_def_property_ui_text(prop, "Tile Number", "Number of the position that this tile covers");
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
|
||||
func = RNA_def_function(srna, "remove", "rna_ImageTile_remove");
|
||||
RNA_def_function_ui_description(func, "Remove this tile from the image");
|
||||
RNA_def_function_flag(func, FUNC_USE_SELF_ID);
|
||||
}
|
||||
|
||||
static void rna_def_image_tiles(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{
|
||||
StructRNA *srna;
|
||||
FunctionRNA *func;
|
||||
PropertyRNA *parm;
|
||||
|
||||
RNA_def_property_srna(cprop, "ImageTiles");
|
||||
srna = RNA_def_struct(brna, "ImageTiles", NULL);
|
||||
RNA_def_struct_sdna(srna, "Image");
|
||||
RNA_def_struct_ui_text(srna, "Image Tiles", "Collection of the image tiles");
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_ImageTile_new");
|
||||
RNA_def_function_ui_description(func, "Add a tile to the image");
|
||||
parm = RNA_def_int(func, "tile_number", 1, 1, INT_MAX, "", "Number of the newly created tile", 1, 100);
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_string(func, "label", NULL, 0, "", "Optional label for the tile");
|
||||
parm = RNA_def_pointer(func, "result", "ImageTile", "", "Newly created image tile");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
||||
func = RNA_def_function(srna, "get", "BKE_image_get_tile");
|
||||
RNA_def_function_ui_description(func, "Get a tile based on its tile number");
|
||||
parm = RNA_def_int(func, "tile_number", 0, 0, INT_MAX, "", "Number of the tile", 1, 100);
|
||||
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
|
||||
parm = RNA_def_pointer(func, "result", "ImageTile", "", "The tile");
|
||||
RNA_def_function_return(func, parm);
|
||||
}
|
||||
|
||||
static void rna_def_image(BlenderRNA *brna)
|
||||
{
|
||||
StructRNA *srna;
|
||||
@@ -782,18 +849,18 @@ static void rna_def_image(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Display Aspect", "Display Aspect for this image, does not affect rendering");
|
||||
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "bindcode", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_int_funcs(prop, "rna_Image_bindcode_get", NULL, NULL);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "Bindcode", "OpenGL bindcode");
|
||||
RNA_def_property_update(prop, NC_IMAGE | ND_DISPLAY, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "render_slots", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "RenderSlot");
|
||||
RNA_def_property_collection_sdna(prop, NULL, "renderslots", NULL);
|
||||
RNA_def_property_ui_text(prop, "Render Slots", "Render slots of the image");
|
||||
rna_def_render_slots(brna, prop);
|
||||
|
||||
prop = RNA_def_property(srna, "tiles", PROP_COLLECTION, PROP_NONE);
|
||||
RNA_def_property_struct_type(prop, "ImageTile");
|
||||
RNA_def_property_collection_sdna(prop, NULL, "tiles", NULL);
|
||||
RNA_def_property_ui_text(prop, "Image Tiles", "Tiles of the image");
|
||||
rna_def_image_tiles(brna, prop);
|
||||
|
||||
/*
|
||||
* Image.has_data and Image.depth are temporary,
|
||||
* Update import_obj.py when they are replaced (Arystan)
|
||||
@@ -875,6 +942,7 @@ static void rna_def_image(BlenderRNA *brna)
|
||||
void RNA_def_image(BlenderRNA *brna)
|
||||
{
|
||||
rna_def_render_slot(brna);
|
||||
rna_def_image_tile(brna);
|
||||
rna_def_image(brna);
|
||||
rna_def_imageuser(brna);
|
||||
rna_def_image_packed_files(brna);
|
||||
|
@@ -181,8 +181,8 @@ static void rna_Image_unpack(Image *image, Main *bmain, ReportList *reports, int
|
||||
if (!BKE_image_has_packedfile(image)) {
|
||||
BKE_report(reports, RPT_ERROR, "Image not packed");
|
||||
}
|
||||
else if (BKE_image_is_animated(image)) {
|
||||
BKE_report(reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
|
||||
else if (BKE_image_has_multiple_ibufs(image)) {
|
||||
BKE_report(reports, RPT_ERROR, "Unpacking movies, image sequences and tiled images not supported");
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -220,9 +220,10 @@ static void rna_Image_scale(Image *image, ReportList *reports, int width, int he
|
||||
}
|
||||
}
|
||||
|
||||
static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int filter, int mag)
|
||||
static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int tile_number, int filter, int mag)
|
||||
{
|
||||
GPUTexture *tex = image->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
ImageTile *tile = BKE_image_get_tile(image, tile_number);
|
||||
GPUTexture *tex = tile->gputexture[TEXTARGET_TEXTURE_2D];
|
||||
int error = GL_NO_ERROR;
|
||||
|
||||
if (tex)
|
||||
@@ -231,6 +232,7 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f
|
||||
ImageUser iuser = {NULL};
|
||||
iuser.framenr = frame;
|
||||
iuser.ok = true;
|
||||
iuser.tile = tile_number;
|
||||
|
||||
void *lock;
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, &lock);
|
||||
@@ -259,7 +261,7 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f
|
||||
glDeleteTextures(1, (GLuint *)&bindcode);
|
||||
}
|
||||
else {
|
||||
image->gputexture[TEXTARGET_TEXTURE_2D] = GPU_texture_from_bindcode(GL_TEXTURE_2D, bindcode);
|
||||
tile->gputexture[TEXTARGET_TEXTURE_2D] = GPU_texture_from_bindcode(GL_TEXTURE_2D, bindcode);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(image, ibuf, lock);
|
||||
@@ -267,14 +269,15 @@ static int rna_Image_gl_load(Image *image, ReportList *reports, int frame, int f
|
||||
return error;
|
||||
}
|
||||
|
||||
static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame, int filter, int mag)
|
||||
static int rna_Image_gl_touch(Image *image, ReportList *reports, int frame, int tile_number, int filter, int mag)
|
||||
{
|
||||
int error = GL_NO_ERROR;
|
||||
|
||||
BKE_image_tag_time(image);
|
||||
|
||||
if (image->gputexture[TEXTARGET_TEXTURE_2D] == NULL)
|
||||
error = rna_Image_gl_load(image, reports, frame, filter, mag);
|
||||
ImageTile *tile = BKE_image_get_tile(image, tile_number);
|
||||
if (tile->gputexture[TEXTARGET_TEXTURE_2D] == NULL)
|
||||
error = rna_Image_gl_load(image, reports, frame, tile_number, filter, mag);
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -359,6 +362,8 @@ void RNA_api_image(StructRNA *srna)
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_int(func, "frame", 0, 0, INT_MAX, "Frame",
|
||||
"Frame of image sequence or movie", 0, INT_MAX);
|
||||
RNA_def_int(func, "tile_number", 0, 0, INT_MAX, "Tile",
|
||||
"Tile of a tiled image", 0, INT_MAX);
|
||||
RNA_def_int(func, "filter", GL_LINEAR_MIPMAP_NEAREST, -INT_MAX, INT_MAX, "Filter",
|
||||
"The texture minifying function to use if the image wasn't loaded", -INT_MAX, INT_MAX);
|
||||
RNA_def_int(func, "mag", GL_LINEAR, -INT_MAX, INT_MAX, "Magnification",
|
||||
@@ -372,6 +377,8 @@ void RNA_api_image(StructRNA *srna)
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_int(func, "frame", 0, 0, INT_MAX, "Frame",
|
||||
"Frame of image sequence or movie", 0, INT_MAX);
|
||||
RNA_def_int(func, "tile_number", 0, 0, INT_MAX, "Tile",
|
||||
"Tile of a tiled image", 0, INT_MAX);
|
||||
RNA_def_int(func, "filter", GL_LINEAR_MIPMAP_NEAREST, -INT_MAX, INT_MAX, "Filter",
|
||||
"The texture minifying function", -INT_MAX, INT_MAX);
|
||||
RNA_def_int(func, "mag", GL_LINEAR, -INT_MAX, INT_MAX, "Magnification",
|
||||
|
@@ -330,13 +330,13 @@ static Lamp *rna_Main_lights_new(Main *bmain, const char *name, int type)
|
||||
return lamp;
|
||||
}
|
||||
|
||||
static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int height, bool alpha, bool float_buffer, bool stereo3d)
|
||||
static Image *rna_Main_images_new(Main *bmain, const char *name, int width, int height, bool alpha, bool float_buffer, bool stereo3d, bool tiled)
|
||||
{
|
||||
char safe_name[MAX_ID_NAME - 2];
|
||||
rna_idname_validate(name, safe_name);
|
||||
|
||||
float color[4] = {0.0, 0.0, 0.0, 1.0};
|
||||
Image *image = BKE_image_add_generated(bmain, width, height, safe_name, alpha ? 32 : 24, float_buffer, 0, color, stereo3d);
|
||||
Image *image = BKE_image_add_generated(bmain, width, height, safe_name, alpha ? 32 : 24, float_buffer, 0, color, stereo3d, tiled);
|
||||
id_us_min(&image->id);
|
||||
return image;
|
||||
}
|
||||
@@ -1004,6 +1004,7 @@ void RNA_def_main_images(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
RNA_def_boolean(func, "alpha", 0, "Alpha", "Use alpha channel");
|
||||
RNA_def_boolean(func, "float_buffer", 0, "Float Buffer", "Create an image with floating point color");
|
||||
RNA_def_boolean(func, "stereo3d", 0, "Stereo 3D", "Create left and right views");
|
||||
RNA_def_boolean(func, "tiled", 0, "Tiled", "Create a tiled image");
|
||||
/* return type */
|
||||
parm = RNA_def_pointer(func, "image", "Image", "", "New image data-block");
|
||||
RNA_def_function_return(func, parm);
|
||||
|
@@ -1069,7 +1069,7 @@ static const EnumPropertyItem *rna_SpaceImageEditor_draw_channels_itemf(
|
||||
void *lock;
|
||||
int zbuf, alpha, totitem = 0;
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
|
||||
alpha = ibuf && (ibuf->channels == 4);
|
||||
zbuf = ibuf && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1));
|
||||
@@ -1174,7 +1174,8 @@ static void rna_SpaceImageEditor_scopes_update(struct bContext *C, struct Pointe
|
||||
ImBuf *ibuf;
|
||||
void *lock;
|
||||
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock);
|
||||
/* TODO(lukas): Support tiles in scopes? */
|
||||
ibuf = ED_space_image_acquire_buffer(sima, &lock, 0);
|
||||
if (ibuf) {
|
||||
ED_space_image_scopes_update(C, sima, ibuf, true);
|
||||
WM_main_add_notifier(NC_IMAGE, sima->image);
|
||||
@@ -2235,6 +2236,14 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Draw Modified Edges", "Draw edges after modifiers are applied");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "tile_grid_shape", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "tile_grid_shape");
|
||||
RNA_def_property_array(prop, 2);
|
||||
RNA_def_property_int_default(prop, 1);
|
||||
RNA_def_property_range(prop, 1, 10);
|
||||
RNA_def_property_ui_text(prop, "Tile Grid Shape", "How many tiles will be shown in the background");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "show_other_objects", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_OTHER);
|
||||
RNA_def_property_ui_text(prop, "Draw Other Objects", "Draw other selected objects that share the same image");
|
||||
@@ -3376,6 +3385,12 @@ static void rna_def_space_image(BlenderRNA *brna)
|
||||
RNA_def_property_float_funcs(prop, "rna_SpaceImageEditor_zoom_get", NULL, NULL);
|
||||
RNA_def_property_ui_text(prop, "Zoom", "Zoom factor");
|
||||
|
||||
prop = RNA_def_property(srna, "current_tile", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "curtile");
|
||||
RNA_def_property_range(prop, 0, 1000);
|
||||
RNA_def_property_ui_text(prop, "Current Tile", "The currently selected tile");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
|
||||
|
||||
/* image draw */
|
||||
prop = RNA_def_property(srna, "show_repeat", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SI_DRAW_TILE);
|
||||
|
@@ -75,9 +75,9 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE
|
||||
node_shader_gpu_tex_mapping(mat, node, in, out);
|
||||
|
||||
if (tex->projection == SHD_PROJ_EQUIRECTANGULAR)
|
||||
GPU_stack_link(mat, node, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata));
|
||||
GPU_stack_link(mat, node, "node_tex_environment_equirectangular", in, out, GPU_image(ima, iuser, isdata, 0));
|
||||
else
|
||||
GPU_stack_link(mat, node, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata));
|
||||
GPU_stack_link(mat, node, "node_tex_environment_mirror_ball", in, out, GPU_image(ima, iuser, isdata, 0));
|
||||
|
||||
ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
|
||||
if (ibuf && (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) == 0 &&
|
||||
|
@@ -67,6 +67,12 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
|
||||
"tex_box_sample_cubic",
|
||||
"tex_box_sample_smart"
|
||||
};
|
||||
static const char *names_tiled[] = {
|
||||
"node_tex_image_tile_linear",
|
||||
"node_tex_image_tile_nearest",
|
||||
"node_tex_image_tile_cubic",
|
||||
"node_tex_image_tile_smart"
|
||||
};
|
||||
|
||||
Image *ima = (Image *)node->id;
|
||||
ImageUser *iuser = NULL;
|
||||
@@ -98,46 +104,59 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat, bNode *node, bNodeExecDat
|
||||
|
||||
node_shader_gpu_tex_mapping(mat, node, in, out);
|
||||
|
||||
switch (tex->projection) {
|
||||
case SHD_PROJ_FLAT:
|
||||
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
|
||||
break;
|
||||
case SHD_PROJ_BOX:
|
||||
GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL),
|
||||
GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
|
||||
&norm);
|
||||
GPU_link(mat, "direction_transform_m4v3", norm,
|
||||
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
|
||||
&norm);
|
||||
GPU_link(mat, gpu_node_name, in[0].link,
|
||||
norm,
|
||||
GPU_image(ima, iuser, isdata),
|
||||
&col1,
|
||||
&col2,
|
||||
&col3);
|
||||
if (do_color_correction) {
|
||||
GPU_link(mat, "srgb_to_linearrgb", col1, &col1);
|
||||
GPU_link(mat, "srgb_to_linearrgb", col2, &col2);
|
||||
GPU_link(mat, "srgb_to_linearrgb", col3, &col3);
|
||||
}
|
||||
GPU_link(mat, "node_tex_image_box", in[0].link,
|
||||
norm,
|
||||
col1, col2, col3,
|
||||
GPU_image(ima, iuser, isdata),
|
||||
GPU_uniform(&blend),
|
||||
&out[0].link,
|
||||
&out[1].link);
|
||||
break;
|
||||
case SHD_PROJ_SPHERE:
|
||||
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
|
||||
GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
|
||||
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
|
||||
break;
|
||||
case SHD_PROJ_TUBE:
|
||||
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
|
||||
GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
|
||||
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata));
|
||||
break;
|
||||
if (ima->source == IMA_SRC_TILED) {
|
||||
GPUNodeLink *map;
|
||||
GPU_link(mat, "node_tex_image_tiled_map", in[0].link, &out[0].link, &map);
|
||||
LISTBASE_FOREACH(ImageTile *, tile, &ima->tiles) {
|
||||
float tile_number = tile->tile_number;
|
||||
GPU_link(mat, names_tiled[tex->interpolation],
|
||||
map, GPU_uniform(&tile_number),
|
||||
GPU_image(ima, iuser, isdata, tile->tile_number),
|
||||
out[0].link, &out[0].link, &out[1].link);
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (tex->projection) {
|
||||
case SHD_PROJ_FLAT:
|
||||
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata, 0));
|
||||
break;
|
||||
case SHD_PROJ_BOX:
|
||||
GPU_link(mat, "direction_transform_m4v3", GPU_builtin(GPU_VIEW_NORMAL),
|
||||
GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
|
||||
&norm);
|
||||
GPU_link(mat, "direction_transform_m4v3", norm,
|
||||
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
|
||||
&norm);
|
||||
GPU_link(mat, gpu_node_name, in[0].link,
|
||||
norm,
|
||||
GPU_image(ima, iuser, isdata, 0),
|
||||
&col1,
|
||||
&col2,
|
||||
&col3);
|
||||
if (do_color_correction) {
|
||||
GPU_link(mat, "srgb_to_linearrgb", col1, &col1);
|
||||
GPU_link(mat, "srgb_to_linearrgb", col2, &col2);
|
||||
GPU_link(mat, "srgb_to_linearrgb", col3, &col3);
|
||||
}
|
||||
GPU_link(mat, "node_tex_image_box", in[0].link,
|
||||
norm,
|
||||
col1, col2, col3,
|
||||
GPU_image(ima, iuser, isdata, 0),
|
||||
GPU_uniform(&blend),
|
||||
&out[0].link,
|
||||
&out[1].link);
|
||||
break;
|
||||
case SHD_PROJ_SPHERE:
|
||||
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
|
||||
GPU_link(mat, "point_map_to_sphere", in[0].link, &in[0].link);
|
||||
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata, 0));
|
||||
break;
|
||||
case SHD_PROJ_TUBE:
|
||||
GPU_link(mat, "point_texco_remap_square", in[0].link, &in[0].link);
|
||||
GPU_link(mat, "point_map_to_tube", in[0].link, &in[0].link);
|
||||
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser, isdata, 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_color_correction && (tex->projection != SHD_PROJ_BOX)) {
|
||||
|
Reference in New Issue
Block a user