ImBuf: Remove pre-2.80 Texture mipmaps/filters
Removes various image filtering/mipmapping leftovers from pre-2.80 days. Code: removes all mipmap handling from ImBuf (which is about half of ImBuf struct size), removes now unused "sample procedural texture with mipmaps" code, now-unused FELINE filter, etc. The osatex parameter to various CPU texture sampling functions is never actually used, which means none of the mipmap code was ever executing. User visible part: there were settings on the legacy Texture data block (as used by Brushes etc.), under Sampling section: "MIP Map", "Gaussian Filter", "Filter Type", "Eccentricity", "Minimum Size" -- they had no effect anywhere, so they are gone, and what remains is only "Interpolation" and "Size". RNA / Python API part: removes the ImageTexture RNA properties corresponding to the above: filter_type, use_mipmap, use_mipmap_gauss, filter_lightprobes, filter_eccentricity, use_filter_size_min. Pull Request: https://projects.blender.org/blender/blender/pulls/139978
This commit is contained in:
committed by
Aras Pranckevicius
parent
3ee94825ce
commit
f685f23434
@@ -1027,7 +1027,6 @@ url_manual_mapping = (
|
||||
("bpy.types.geometrynodesetinstancetransform*", "modeling/geometry_nodes/instances/set_instance_transform.html#bpy-types-geometrynodesetinstancetransform"),
|
||||
("bpy.types.greasepencilv3.ghost_after_range*", "grease_pencil/properties/onion_skinning.html#bpy-types-greasepencilv3-ghost-after-range"),
|
||||
("bpy.types.imagetexture.use_calculate_alpha*", "render/materials/legacy_textures/types/image_movie.html#bpy-types-imagetexture-use-calculate-alpha"),
|
||||
("bpy.types.imagetexture.use_filter_size_min*", "render/materials/legacy_textures/types/image_movie.html#bpy-types-imagetexture-use-filter-size-min"),
|
||||
("bpy.types.material.max_vertex_displacement*", "render/eevee/material_settings.html#bpy-types-material-max-vertex-displacement"),
|
||||
("bpy.types.material.use_raytrace_refraction*", "render/eevee/material_settings.html#bpy-types-material-use-raytrace-refraction"),
|
||||
("bpy.types.materialgpencilstyle.show_stroke*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-show-stroke"),
|
||||
@@ -1400,7 +1399,6 @@ url_manual_mapping = (
|
||||
("bpy.types.greasepencilv3.use_onion_loop*", "grease_pencil/properties/onion_skinning.html#bpy-types-greasepencilv3-use-onion-loop"),
|
||||
("bpy.types.imageformatsettings.exr_codec*", "files/media/image_formats.html#bpy-types-imageformatsettings-exr-codec"),
|
||||
("bpy.types.imagepaint.use_normal_falloff*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-use-normal-falloff"),
|
||||
("bpy.types.imagetexture.use_mipmap_gauss*", "render/materials/legacy_textures/types/image_movie.html#bpy-types-imagetexture-use-mipmap-gauss"),
|
||||
("bpy.types.layercollection.hide_viewport*", "editors/outliner/interface.html#bpy-types-layercollection-hide-viewport"),
|
||||
("bpy.types.layercollection.indirect_only*", "editors/outliner/interface.html#bpy-types-layercollection-indirect-only"),
|
||||
("bpy.types.light.use_absolute_resolution*", "render/eevee/light_settings.html#bpy-types-light-use-absolute-resolution"),
|
||||
@@ -2156,7 +2154,6 @@ url_manual_mapping = (
|
||||
("bpy.types.image.use_view_as_render*", "editors/image/image_settings.html#bpy-types-image-use-view-as-render"),
|
||||
("bpy.types.imagepaint.interpolation*", "sculpt_paint/texture_paint/tool_settings/texture_slots.html#bpy-types-imagepaint-interpolation"),
|
||||
("bpy.types.imagetexture.filter_size*", "render/materials/legacy_textures/types/image_movie.html#bpy-types-imagetexture-filter-size"),
|
||||
("bpy.types.imagetexture.filter_type*", "render/materials/legacy_textures/types/image_movie.html#bpy-types-imagetexture-filter-type"),
|
||||
("bpy.types.keyingset.bl_description*", "animation/keyframes/keying_sets.html#bpy-types-keyingset-bl-description"),
|
||||
("bpy.types.linestyle*modifier_noise*", "render/freestyle/view_layer/line_style/modifiers/color/noise.html#bpy-types-linestyle-modifier-noise"),
|
||||
("bpy.types.maintainvolumeconstraint*", "animation/constraints/transform/maintain_volume.html#bpy-types-maintainvolumeconstraint"),
|
||||
@@ -2335,7 +2332,6 @@ url_manual_mapping = (
|
||||
("bpy.types.greasepencilgrid.offset*", "grease_pencil/properties/display.html#bpy-types-greasepencilgrid-offset"),
|
||||
("bpy.types.greasepencillayer.scale*", "grease_pencil/properties/layers.html#bpy-types-greasepencillayer-scale"),
|
||||
("bpy.types.imagepaint.normal_angle*", "sculpt_paint/brush/falloff.html#bpy-types-imagepaint-normal-angle"),
|
||||
("bpy.types.imagetexture.use_mipmap*", "render/materials/legacy_textures/types/image_movie.html#bpy-types-imagetexture-use-mipmap"),
|
||||
("bpy.types.keyingsetpath.data_path*", "animation/keyframes/keying_sets.html#bpy-types-keyingsetpath-data-path"),
|
||||
("bpy.types.keyingsets.active_index*", "animation/keyframes/keying_sets.html#bpy-types-keyingsets-active-index"),
|
||||
("bpy.types.keymapitem.key_modifier*", "editors/preferences/keymap.html#bpy-types-keymapitem-key-modifier"),
|
||||
|
||||
@@ -408,20 +408,6 @@ class TEXTURE_PT_image_settings(TextureTypePanel, Panel):
|
||||
layout.template_image(tex, "image", tex.image_user)
|
||||
|
||||
|
||||
def texture_filter_common(tex, layout):
|
||||
layout.prop(tex, "filter_type", text="Filter Type")
|
||||
|
||||
if tex.use_mipmap and tex.filter_type in {'AREA', 'EWA', 'FELINE'}:
|
||||
col = layout.column()
|
||||
if tex.filter_type == 'FELINE':
|
||||
col.prop(tex, "filter_lightprobes", text="Light Probes")
|
||||
else:
|
||||
col.prop(tex, "filter_eccentricity", text="Eccentricity")
|
||||
|
||||
layout.prop(tex, "filter_size", text="Size")
|
||||
layout.prop(tex, "use_filter_size_min", text="Minimum Size")
|
||||
|
||||
|
||||
class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
|
||||
bl_label = "Sampling"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
@@ -442,18 +428,7 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
|
||||
|
||||
col = flow.column()
|
||||
col.prop(tex, "use_interpolation")
|
||||
|
||||
col.separator()
|
||||
|
||||
col = flow.column()
|
||||
col.prop(tex, "use_mipmap")
|
||||
sub = col.column()
|
||||
sub.active = tex.use_mipmap
|
||||
sub.prop(tex, "use_mipmap_gauss", text="Gaussian Filter")
|
||||
|
||||
col.separator()
|
||||
|
||||
texture_filter_common(tex, flow)
|
||||
col.prop(tex, "filter_size", text="Size")
|
||||
|
||||
|
||||
class TEXTURE_PT_image_alpha(TextureTypePanel, Panel):
|
||||
|
||||
@@ -882,8 +882,7 @@ static void do_texture_effector(EffectorCache *eff,
|
||||
madd_v3_v3fl(tex_co, efd->nor, fac);
|
||||
}
|
||||
|
||||
hasrgb = multitex_ext(
|
||||
eff->pd->tex, tex_co, nullptr, nullptr, 0, result, 0, nullptr, true, false);
|
||||
hasrgb = multitex_ext(eff->pd->tex, tex_co, result, 0, nullptr, true, false);
|
||||
|
||||
if (hasrgb && mode == PFIELD_TEX_RGB) {
|
||||
force[0] = (0.5f - result->trgba[0]) * strength;
|
||||
@@ -894,15 +893,15 @@ static void do_texture_effector(EffectorCache *eff,
|
||||
strength /= nabla;
|
||||
|
||||
tex_co[0] += nabla;
|
||||
multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 1, 0, nullptr, true, false);
|
||||
multitex_ext(eff->pd->tex, tex_co, result + 1, 0, nullptr, true, false);
|
||||
|
||||
tex_co[0] -= nabla;
|
||||
tex_co[1] += nabla;
|
||||
multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 2, 0, nullptr, true, false);
|
||||
multitex_ext(eff->pd->tex, tex_co, result + 2, 0, nullptr, true, false);
|
||||
|
||||
tex_co[1] -= nabla;
|
||||
tex_co[2] += nabla;
|
||||
multitex_ext(eff->pd->tex, tex_co, nullptr, nullptr, 0, result + 3, 0, nullptr, true, false);
|
||||
multitex_ext(eff->pd->tex, tex_co, result + 3, 0, nullptr, true, false);
|
||||
|
||||
if (mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we don't have rgb fall back to grad */
|
||||
/* generate intensity if texture only has rgb value */
|
||||
|
||||
@@ -1556,11 +1556,6 @@ static uintptr_t image_mem_size(Image *image)
|
||||
}
|
||||
|
||||
size += IMB_get_size_in_memory(ibuf);
|
||||
|
||||
for (int level = 0; level < IMB_MIPMAP_LEVELS; level++) {
|
||||
ImBuf *ibufm = ibuf->mipmap[level];
|
||||
size += IMB_get_size_in_memory(ibufm);
|
||||
}
|
||||
}
|
||||
IMB_moviecacheIter_free(iter);
|
||||
}
|
||||
|
||||
@@ -796,13 +796,6 @@ void blo_do_versions_250(FileData *fd, Library * /*lib*/, Main *bmain)
|
||||
}
|
||||
}
|
||||
|
||||
/* texture filter */
|
||||
LISTBASE_FOREACH (Tex *, tex, &bmain->textures) {
|
||||
if (tex->afmax == 0) {
|
||||
tex->afmax = 8;
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (Scene *, sce, &bmain->scenes) {
|
||||
ToolSettings *ts = sce->toolsettings;
|
||||
if (!ts->uv_selectmode || ts->vgroup_weight == 0.0f) {
|
||||
|
||||
@@ -334,12 +334,6 @@ static bool write_internal_bake_pixels(Image *image,
|
||||
ibuf->userflags |= IB_RECT_INVALID;
|
||||
}
|
||||
|
||||
/* force mipmap recalc */
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
IMB_free_mipmaps(ibuf);
|
||||
}
|
||||
|
||||
BKE_image_release_ibuf(image, ibuf, nullptr);
|
||||
|
||||
if (mask_buffer) {
|
||||
|
||||
@@ -159,10 +159,6 @@ void imapaint_image_update(
|
||||
return;
|
||||
}
|
||||
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
}
|
||||
|
||||
IMB_partial_display_buffer_update_delayed(ibuf,
|
||||
imapaintpartial.dirty_region.xmin,
|
||||
imapaintpartial.dirty_region.ymin,
|
||||
|
||||
@@ -2860,10 +2860,6 @@ static wmOperatorStatus image_flip_exec(bContext *C, wmOperator *op)
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
BKE_image_mark_dirty(ima, ibuf);
|
||||
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
}
|
||||
|
||||
ED_image_undo_push_end();
|
||||
|
||||
BKE_image_partial_update_mark_full_update(ima);
|
||||
@@ -2934,10 +2930,6 @@ static wmOperatorStatus image_rotate_orthogonal_exec(bContext *C, wmOperator *op
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
BKE_image_mark_dirty(ima, ibuf);
|
||||
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
}
|
||||
|
||||
ED_image_undo_push_end();
|
||||
|
||||
BKE_image_partial_update_mark_full_update(ima);
|
||||
@@ -3201,10 +3193,6 @@ static wmOperatorStatus image_invert_exec(bContext *C, wmOperator *op)
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
BKE_image_mark_dirty(ima, ibuf);
|
||||
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
}
|
||||
|
||||
ED_image_undo_push_end();
|
||||
|
||||
BKE_image_partial_update_mark_full_update(ima);
|
||||
|
||||
@@ -349,9 +349,6 @@ static void ptile_restore_runtime_map(PaintTileMap *paint_tile_map)
|
||||
if (ibuf->float_buffer.data) {
|
||||
ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
|
||||
}
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID; /* Force MIP-MAP recreation. */
|
||||
}
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
|
||||
BKE_image_release_ibuf(image, ibuf, nullptr);
|
||||
@@ -633,9 +630,6 @@ static void uhandle_restore_list(ListBase *undo_handles, bool use_init)
|
||||
if (ibuf->float_buffer.data) {
|
||||
ibuf->userflags |= IB_RECT_INVALID; /* Force recreate of char `rect` */
|
||||
}
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID; /* Force MIP-MAP recreation. */
|
||||
}
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
|
||||
DEG_id_tag_update(&image->id, 0);
|
||||
|
||||
@@ -120,8 +120,7 @@ ImBuf *IMB_allocFromBuffer(const uint8_t *byte_buffer,
|
||||
* Assign the content of the corresponding buffer with the given data and ownership.
|
||||
* The current content of the buffer is released corresponding to its ownership configuration.
|
||||
*
|
||||
* \note Does not modify the topology (width, height, number of channels)
|
||||
* or the mipmaps in any way.
|
||||
* \note Does not modify the topology (width, height, number of channels).
|
||||
*/
|
||||
void IMB_assign_byte_buffer(ImBuf *ibuf, uint8_t *buffer_data, ImBufOwnership ownership);
|
||||
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership);
|
||||
@@ -130,8 +129,7 @@ void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership own
|
||||
* Assign the content and the color space of the corresponding buffer the data from the given
|
||||
* buffer.
|
||||
*
|
||||
* \note Does not modify the topology (width, height, number of channels)
|
||||
* or the mipmaps in any way.
|
||||
* \note Does not modify the topology (width, height, number of channels).
|
||||
*
|
||||
* \note The ownership of the data in the source buffer is ignored.
|
||||
*/
|
||||
@@ -305,20 +303,9 @@ void IMB_mask_clear(ImBuf *ibuf, const char *mask, int val);
|
||||
* will be used for the average. The mask will be set to one for the pixels which were written.
|
||||
*/
|
||||
void IMB_filter_extend(ImBuf *ibuf, char *mask, int filter);
|
||||
/**
|
||||
* Frees too (if there) and recreates new data.
|
||||
*/
|
||||
void IMB_makemipmap(ImBuf *ibuf, int use_filter);
|
||||
/**
|
||||
* Thread-safe version, only recreates existing maps.
|
||||
*/
|
||||
void IMB_remakemipmap(ImBuf *ibuf, int use_filter);
|
||||
ImBuf *IMB_getmipmap(ImBuf *ibuf, int level);
|
||||
|
||||
void IMB_filtery(ImBuf *ibuf);
|
||||
|
||||
ImBuf *IMB_onehalf(ImBuf *ibuf1);
|
||||
|
||||
/** Interpolation filter used by `IMB_scale`. */
|
||||
enum class IMBScaleFilter {
|
||||
/** No filtering (point sampling). This is fastest but lowest quality. */
|
||||
@@ -463,9 +450,6 @@ void IMB_buffer_byte_from_byte(unsigned char *rect_to,
|
||||
void IMB_alpha_under_color_float(float *rect_float, int x, int y, float backcol[3]);
|
||||
void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, const float backcol[3]);
|
||||
|
||||
ImBuf *IMB_half_x(ImBuf *ibuf1);
|
||||
ImBuf *IMB_half_y(ImBuf *ibuf1);
|
||||
|
||||
void IMB_flipx(ImBuf *ibuf);
|
||||
void IMB_flipy(ImBuf *ibuf);
|
||||
|
||||
@@ -550,7 +534,7 @@ void *imb_alloc_pixels(unsigned int x,
|
||||
bool IMB_alloc_byte_pixels(ImBuf *ibuf, bool initialize_pixels = true);
|
||||
|
||||
/**
|
||||
* Deallocate image byte storage. Also deallocates any mipmaps.
|
||||
* Deallocate image byte storage.
|
||||
*/
|
||||
void IMB_free_byte_pixels(ImBuf *ibuf);
|
||||
|
||||
@@ -562,16 +546,11 @@ bool IMB_alloc_float_pixels(ImBuf *ibuf,
|
||||
const unsigned int channels,
|
||||
bool initialize_pixels = true);
|
||||
/**
|
||||
* Deallocate image float storage. Also deallocates any mipmaps.
|
||||
* Deallocate image float storage.
|
||||
*/
|
||||
void IMB_free_float_pixels(ImBuf *ibuf);
|
||||
|
||||
/**
|
||||
* Deallocate mipmaps.
|
||||
*/
|
||||
void IMB_free_mipmaps(ImBuf *ibuf);
|
||||
|
||||
/** Deallocate all CPU side data storage (byte, float, encoded, mipmaps). */
|
||||
/** Deallocate all CPU side data storage (byte, float, encoded). */
|
||||
void IMB_free_all_data(ImBuf *ibuf);
|
||||
|
||||
/* Free the GPU textures of the given image buffer, leaving the CPU buffers unchanged.
|
||||
|
||||
@@ -24,7 +24,6 @@ class ColorSpace;
|
||||
}
|
||||
using ColorSpace = blender::ocio::ColorSpace;
|
||||
|
||||
#define IMB_MIPMAP_LEVELS 20
|
||||
#define IMB_FILEPATH_SIZE 1024
|
||||
|
||||
/**
|
||||
@@ -220,11 +219,6 @@ struct ImBuf {
|
||||
/** Amount of dithering to apply, when converting float -> byte. */
|
||||
float dither;
|
||||
|
||||
/* mipmapping */
|
||||
/** MipMap levels, a series of halved images */
|
||||
ImBuf *mipmap[IMB_MIPMAP_LEVELS];
|
||||
int miptot, miplevel;
|
||||
|
||||
/* externally used data */
|
||||
/** reference index for ImBuf lists */
|
||||
int index;
|
||||
@@ -273,8 +267,6 @@ struct ImBuf {
|
||||
enum {
|
||||
/** image needs to be saved is not the same as filename */
|
||||
IB_BITMAPDIRTY = (1 << 1),
|
||||
/** image mipmaps are invalid, need recreate */
|
||||
IB_MIPMAP_INVALID = (1 << 2),
|
||||
/** float buffer changed, needs recreation of byte rect */
|
||||
IB_RECT_INVALID = (1 << 3),
|
||||
/** either float or byte buffer changed, need to re-calculate display buffers */
|
||||
|
||||
@@ -18,8 +18,3 @@ void IMB_premultiply_rect_float(float *rect_float, int channels, int w, int h);
|
||||
|
||||
void IMB_unpremultiply_rect(uint8_t *rect, char planes, int w, int h);
|
||||
void IMB_unpremultiply_rect_float(float *rect_float, int channels, int w, int h);
|
||||
|
||||
/**
|
||||
* Result in ibuf2, scaling should be done correctly.
|
||||
*/
|
||||
void imb_onehalf_no_alloc(ImBuf *ibuf2, ImBuf *ibuf1);
|
||||
|
||||
@@ -161,32 +161,12 @@ auto imb_steal_buffer_data(BufferType &buffer) -> decltype(BufferType::data)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void IMB_free_mipmaps(ImBuf *ibuf)
|
||||
{
|
||||
int a;
|
||||
|
||||
/* Do not trust ibuf->miptot, in some cases IMB_remakemipmap can leave unfreed unused levels,
|
||||
* leading to memory leaks... */
|
||||
for (a = 0; a < IMB_MIPMAP_LEVELS; a++) {
|
||||
if (ibuf->mipmap[a] != nullptr) {
|
||||
IMB_freeImBuf(ibuf->mipmap[a]);
|
||||
ibuf->mipmap[a] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ibuf->miptot = 0;
|
||||
}
|
||||
|
||||
void IMB_free_float_pixels(ImBuf *ibuf)
|
||||
{
|
||||
if (ibuf == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
imb_free_buffer(ibuf->float_buffer);
|
||||
|
||||
IMB_free_mipmaps(ibuf);
|
||||
|
||||
ibuf->flags &= ~IB_float_data;
|
||||
}
|
||||
|
||||
@@ -195,11 +175,7 @@ void IMB_free_byte_pixels(ImBuf *ibuf)
|
||||
if (ibuf == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
imb_free_buffer(ibuf->byte_buffer);
|
||||
|
||||
IMB_free_mipmaps(ibuf);
|
||||
|
||||
ibuf->flags &= ~IB_byte_data;
|
||||
}
|
||||
|
||||
@@ -359,11 +335,8 @@ bool IMB_alloc_float_pixels(ImBuf *ibuf, const uint channels, bool initialize_pi
|
||||
return false;
|
||||
}
|
||||
|
||||
/* NOTE: Follows the historical code.
|
||||
* Is unclear if it is desired or not to free mipmaps. If mipmaps are to be preserved a simple
|
||||
* `imb_free_buffer(ibuf->float_buffer)` can be used instead. */
|
||||
if (ibuf->float_buffer.data) {
|
||||
IMB_free_float_pixels(ibuf); /* frees mipmap too, hrm */
|
||||
IMB_free_float_pixels(ibuf);
|
||||
}
|
||||
|
||||
if (!imb_alloc_buffer(
|
||||
@@ -386,8 +359,6 @@ bool IMB_alloc_byte_pixels(ImBuf *ibuf, bool initialize_pixels)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Don't call IMB_free_byte_pixels, it frees mipmaps,
|
||||
* this call is used only too give float buffers display. */
|
||||
imb_free_buffer(ibuf->byte_buffer);
|
||||
|
||||
if (!imb_alloc_buffer(
|
||||
@@ -600,7 +571,7 @@ ImBuf *IMB_dupImBuf(const ImBuf *ibuf1)
|
||||
{
|
||||
ImBuf *ibuf2, tbuf;
|
||||
int flags = IB_uninitialized_pixels;
|
||||
int a, x, y;
|
||||
int x, y;
|
||||
|
||||
if (ibuf1 == nullptr) {
|
||||
return nullptr;
|
||||
@@ -656,9 +627,6 @@ ImBuf *IMB_dupImBuf(const ImBuf *ibuf1)
|
||||
tbuf.byte_buffer = ibuf2->byte_buffer;
|
||||
tbuf.float_buffer = ibuf2->float_buffer;
|
||||
tbuf.encoded_buffer = ibuf2->encoded_buffer;
|
||||
for (a = 0; a < IMB_MIPMAP_LEVELS; a++) {
|
||||
tbuf.mipmap[a] = nullptr;
|
||||
}
|
||||
tbuf.dds_data.data = nullptr;
|
||||
|
||||
/* Set `malloc` flag. */
|
||||
@@ -686,7 +654,6 @@ size_t IMB_get_pixel_count(const ImBuf *ibuf)
|
||||
|
||||
size_t IMB_get_size_in_memory(const ImBuf *ibuf)
|
||||
{
|
||||
int a;
|
||||
size_t size = 0, channel_size = 0;
|
||||
|
||||
size += sizeof(ImBuf);
|
||||
@@ -701,13 +668,5 @@ size_t IMB_get_size_in_memory(const ImBuf *ibuf)
|
||||
|
||||
size += channel_size * IMB_get_pixel_count(ibuf) * size_t(ibuf->channels);
|
||||
|
||||
if (ibuf->miptot) {
|
||||
for (a = 0; a < ibuf->miptot; a++) {
|
||||
if (ibuf->mipmap[a]) {
|
||||
size += IMB_get_size_in_memory(ibuf->mipmap[a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -97,123 +97,6 @@ void IMB_filtery(ImBuf *ibuf)
|
||||
}
|
||||
}
|
||||
|
||||
static void imb_filterN(ImBuf *out, ImBuf *in)
|
||||
{
|
||||
BLI_assert(out->channels == in->channels);
|
||||
BLI_assert(out->x == in->x && out->y == in->y);
|
||||
|
||||
const int channels = in->channels;
|
||||
const int rowlen = in->x;
|
||||
|
||||
if (in->byte_buffer.data && out->byte_buffer.data) {
|
||||
for (int y = 0; y < in->y; y++) {
|
||||
/* setup rows */
|
||||
const char *row2 = (const char *)in->byte_buffer.data + y * channels * rowlen;
|
||||
const char *row1 = (y == 0) ? row2 : row2 - channels * rowlen;
|
||||
const char *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen;
|
||||
|
||||
char *cp = (char *)out->byte_buffer.data + y * channels * rowlen;
|
||||
|
||||
for (int x = 0; x < rowlen; x++) {
|
||||
const char *r11, *r13, *r21, *r23, *r31, *r33;
|
||||
|
||||
if (x == 0) {
|
||||
r11 = row1;
|
||||
r21 = row2;
|
||||
r31 = row3;
|
||||
}
|
||||
else {
|
||||
r11 = row1 - channels;
|
||||
r21 = row2 - channels;
|
||||
r31 = row3 - channels;
|
||||
}
|
||||
|
||||
if (x == rowlen - 1) {
|
||||
r13 = row1;
|
||||
r23 = row2;
|
||||
r33 = row3;
|
||||
}
|
||||
else {
|
||||
r13 = row1 + channels;
|
||||
r23 = row2 + channels;
|
||||
r33 = row3 + channels;
|
||||
}
|
||||
|
||||
cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] +
|
||||
2 * row3[0] + r33[0]) >>
|
||||
4;
|
||||
cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] +
|
||||
2 * row3[1] + r33[1]) >>
|
||||
4;
|
||||
cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] +
|
||||
2 * row3[2] + r33[2]) >>
|
||||
4;
|
||||
cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] +
|
||||
2 * row3[3] + r33[3]) >>
|
||||
4;
|
||||
cp += channels;
|
||||
row1 += channels;
|
||||
row2 += channels;
|
||||
row3 += channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in->float_buffer.data && out->float_buffer.data) {
|
||||
for (int y = 0; y < in->y; y++) {
|
||||
/* setup rows */
|
||||
const float *row2 = (const float *)in->float_buffer.data + y * channels * rowlen;
|
||||
const float *row1 = (y == 0) ? row2 : row2 - channels * rowlen;
|
||||
const float *row3 = (y == in->y - 1) ? row2 : row2 + channels * rowlen;
|
||||
|
||||
float *cp = out->float_buffer.data + y * channels * rowlen;
|
||||
|
||||
for (int x = 0; x < rowlen; x++) {
|
||||
const float *r11, *r13, *r21, *r23, *r31, *r33;
|
||||
|
||||
if (x == 0) {
|
||||
r11 = row1;
|
||||
r21 = row2;
|
||||
r31 = row3;
|
||||
}
|
||||
else {
|
||||
r11 = row1 - channels;
|
||||
r21 = row2 - channels;
|
||||
r31 = row3 - channels;
|
||||
}
|
||||
|
||||
if (x == rowlen - 1) {
|
||||
r13 = row1;
|
||||
r23 = row2;
|
||||
r33 = row3;
|
||||
}
|
||||
else {
|
||||
r13 = row1 + channels;
|
||||
r23 = row2 + channels;
|
||||
r33 = row3 + channels;
|
||||
}
|
||||
|
||||
cp[0] = (r11[0] + 2 * row1[0] + r13[0] + 2 * r21[0] + 4 * row2[0] + 2 * r23[0] + r31[0] +
|
||||
2 * row3[0] + r33[0]) *
|
||||
(1.0f / 16.0f);
|
||||
cp[1] = (r11[1] + 2 * row1[1] + r13[1] + 2 * r21[1] + 4 * row2[1] + 2 * r23[1] + r31[1] +
|
||||
2 * row3[1] + r33[1]) *
|
||||
(1.0f / 16.0f);
|
||||
cp[2] = (r11[2] + 2 * row1[2] + r13[2] + 2 * r21[2] + 4 * row2[2] + 2 * r23[2] + r31[2] +
|
||||
2 * row3[2] + r33[2]) *
|
||||
(1.0f / 16.0f);
|
||||
cp[3] = (r11[3] + 2 * row1[3] + r13[3] + 2 * r21[3] + 4 * row2[3] + 2 * r23[3] + r31[3] +
|
||||
2 * row3[3] + r33[3]) *
|
||||
(1.0f / 16.0f);
|
||||
cp += channels;
|
||||
row1 += channels;
|
||||
row2 += channels;
|
||||
row3 += channels;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_mask_filter_extend(char *mask, int width, int height)
|
||||
{
|
||||
const char *row1, *row2, *row3;
|
||||
@@ -449,85 +332,6 @@ void IMB_filter_extend(ImBuf *ibuf, char *mask, int filter)
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_remakemipmap(ImBuf *ibuf, int use_filter)
|
||||
{
|
||||
ImBuf *hbuf = ibuf;
|
||||
int curmap = 0;
|
||||
|
||||
ibuf->miptot = 1;
|
||||
|
||||
while (curmap < IMB_MIPMAP_LEVELS) {
|
||||
|
||||
if (ibuf->mipmap[curmap]) {
|
||||
|
||||
if (use_filter) {
|
||||
ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags);
|
||||
imb_filterN(nbuf, hbuf);
|
||||
imb_onehalf_no_alloc(ibuf->mipmap[curmap], nbuf);
|
||||
IMB_freeImBuf(nbuf);
|
||||
}
|
||||
else {
|
||||
imb_onehalf_no_alloc(ibuf->mipmap[curmap], hbuf);
|
||||
}
|
||||
}
|
||||
|
||||
ibuf->miptot = curmap + 2;
|
||||
hbuf = ibuf->mipmap[curmap];
|
||||
if (hbuf) {
|
||||
hbuf->miplevel = curmap + 1;
|
||||
}
|
||||
|
||||
if (!hbuf || (hbuf->x <= 2 && hbuf->y <= 2)) {
|
||||
break;
|
||||
}
|
||||
|
||||
curmap++;
|
||||
}
|
||||
}
|
||||
|
||||
void IMB_makemipmap(ImBuf *ibuf, int use_filter)
|
||||
{
|
||||
ImBuf *hbuf = ibuf;
|
||||
int curmap = 0;
|
||||
|
||||
IMB_free_mipmaps(ibuf);
|
||||
|
||||
/* no mipmap for non RGBA images */
|
||||
if (ibuf->float_buffer.data && ibuf->channels < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
ibuf->miptot = 1;
|
||||
|
||||
while (curmap < IMB_MIPMAP_LEVELS) {
|
||||
if (use_filter) {
|
||||
ImBuf *nbuf = IMB_allocImBuf(hbuf->x, hbuf->y, hbuf->planes, hbuf->flags);
|
||||
imb_filterN(nbuf, hbuf);
|
||||
ibuf->mipmap[curmap] = IMB_onehalf(nbuf);
|
||||
IMB_freeImBuf(nbuf);
|
||||
}
|
||||
else {
|
||||
ibuf->mipmap[curmap] = IMB_onehalf(hbuf);
|
||||
}
|
||||
|
||||
ibuf->miptot = curmap + 2;
|
||||
hbuf = ibuf->mipmap[curmap];
|
||||
hbuf->miplevel = curmap + 1;
|
||||
|
||||
if (hbuf->x < 2 && hbuf->y < 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
curmap++;
|
||||
}
|
||||
}
|
||||
|
||||
ImBuf *IMB_getmipmap(ImBuf *ibuf, int level)
|
||||
{
|
||||
CLAMP(level, 0, ibuf->miptot - 1);
|
||||
return (level == 0) ? ibuf : ibuf->mipmap[level - 1];
|
||||
}
|
||||
|
||||
void IMB_premultiply_rect(uint8_t *rect, char planes, int w, int h)
|
||||
{
|
||||
uint8_t *cp;
|
||||
|
||||
@@ -25,319 +25,6 @@ using blender::float3;
|
||||
using blender::float4;
|
||||
using blender::uchar4;
|
||||
|
||||
static void imb_half_x_no_alloc(ImBuf *ibuf2, ImBuf *ibuf1)
|
||||
{
|
||||
uchar *p1, *_p1, *dest;
|
||||
short a, r, g, b;
|
||||
int x, y;
|
||||
float af, rf, gf, bf, *p1f, *_p1f, *destf;
|
||||
bool do_rect, do_float;
|
||||
|
||||
do_rect = (ibuf1->byte_buffer.data != nullptr);
|
||||
do_float = (ibuf1->float_buffer.data != nullptr && ibuf2->float_buffer.data != nullptr);
|
||||
|
||||
_p1 = ibuf1->byte_buffer.data;
|
||||
dest = ibuf2->byte_buffer.data;
|
||||
|
||||
_p1f = ibuf1->float_buffer.data;
|
||||
destf = ibuf2->float_buffer.data;
|
||||
|
||||
for (y = ibuf2->y; y > 0; y--) {
|
||||
p1 = _p1;
|
||||
p1f = _p1f;
|
||||
for (x = ibuf2->x; x > 0; x--) {
|
||||
if (do_rect) {
|
||||
a = *(p1++);
|
||||
b = *(p1++);
|
||||
g = *(p1++);
|
||||
r = *(p1++);
|
||||
a += *(p1++);
|
||||
b += *(p1++);
|
||||
g += *(p1++);
|
||||
r += *(p1++);
|
||||
*(dest++) = a >> 1;
|
||||
*(dest++) = b >> 1;
|
||||
*(dest++) = g >> 1;
|
||||
*(dest++) = r >> 1;
|
||||
}
|
||||
if (do_float) {
|
||||
af = *(p1f++);
|
||||
bf = *(p1f++);
|
||||
gf = *(p1f++);
|
||||
rf = *(p1f++);
|
||||
af += *(p1f++);
|
||||
bf += *(p1f++);
|
||||
gf += *(p1f++);
|
||||
rf += *(p1f++);
|
||||
*(destf++) = 0.5f * af;
|
||||
*(destf++) = 0.5f * bf;
|
||||
*(destf++) = 0.5f * gf;
|
||||
*(destf++) = 0.5f * rf;
|
||||
}
|
||||
}
|
||||
if (do_rect) {
|
||||
_p1 += (ibuf1->x << 2);
|
||||
}
|
||||
if (do_float) {
|
||||
_p1f += (ibuf1->x << 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImBuf *IMB_half_x(ImBuf *ibuf1)
|
||||
{
|
||||
ImBuf *ibuf2;
|
||||
|
||||
if (ibuf1 == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (ibuf1->byte_buffer.data == nullptr && ibuf1->float_buffer.data == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ibuf1->x <= 1) {
|
||||
return IMB_dupImBuf(ibuf1);
|
||||
}
|
||||
|
||||
ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, ibuf1->y, ibuf1->planes, ibuf1->flags);
|
||||
if (ibuf2 == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
imb_half_x_no_alloc(ibuf2, ibuf1);
|
||||
|
||||
return ibuf2;
|
||||
}
|
||||
|
||||
static void imb_half_y_no_alloc(ImBuf *ibuf2, ImBuf *ibuf1)
|
||||
{
|
||||
uchar *p1, *p2, *_p1, *dest;
|
||||
short a, r, g, b;
|
||||
int x, y;
|
||||
float af, rf, gf, bf, *p1f, *p2f, *_p1f, *destf;
|
||||
|
||||
p1 = p2 = nullptr;
|
||||
p1f = p2f = nullptr;
|
||||
|
||||
const bool do_rect = (ibuf1->byte_buffer.data != nullptr);
|
||||
const bool do_float = (ibuf1->float_buffer.data != nullptr &&
|
||||
ibuf2->float_buffer.data != nullptr);
|
||||
|
||||
_p1 = ibuf1->byte_buffer.data;
|
||||
dest = ibuf2->byte_buffer.data;
|
||||
_p1f = ibuf1->float_buffer.data;
|
||||
destf = ibuf2->float_buffer.data;
|
||||
|
||||
for (y = ibuf2->y; y > 0; y--) {
|
||||
if (do_rect) {
|
||||
p1 = _p1;
|
||||
p2 = _p1 + (ibuf1->x << 2);
|
||||
}
|
||||
if (do_float) {
|
||||
p1f = _p1f;
|
||||
p2f = _p1f + (ibuf1->x << 2);
|
||||
}
|
||||
for (x = ibuf2->x; x > 0; x--) {
|
||||
if (do_rect) {
|
||||
a = *(p1++);
|
||||
b = *(p1++);
|
||||
g = *(p1++);
|
||||
r = *(p1++);
|
||||
a += *(p2++);
|
||||
b += *(p2++);
|
||||
g += *(p2++);
|
||||
r += *(p2++);
|
||||
*(dest++) = a >> 1;
|
||||
*(dest++) = b >> 1;
|
||||
*(dest++) = g >> 1;
|
||||
*(dest++) = r >> 1;
|
||||
}
|
||||
if (do_float) {
|
||||
af = *(p1f++);
|
||||
bf = *(p1f++);
|
||||
gf = *(p1f++);
|
||||
rf = *(p1f++);
|
||||
af += *(p2f++);
|
||||
bf += *(p2f++);
|
||||
gf += *(p2f++);
|
||||
rf += *(p2f++);
|
||||
*(destf++) = 0.5f * af;
|
||||
*(destf++) = 0.5f * bf;
|
||||
*(destf++) = 0.5f * gf;
|
||||
*(destf++) = 0.5f * rf;
|
||||
}
|
||||
}
|
||||
if (do_rect) {
|
||||
_p1 += (ibuf1->x << 3);
|
||||
}
|
||||
if (do_float) {
|
||||
_p1f += (ibuf1->x << 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImBuf *IMB_half_y(ImBuf *ibuf1)
|
||||
{
|
||||
ImBuf *ibuf2;
|
||||
|
||||
if (ibuf1 == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (ibuf1->byte_buffer.data == nullptr && ibuf1->float_buffer.data == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ibuf1->y <= 1) {
|
||||
return IMB_dupImBuf(ibuf1);
|
||||
}
|
||||
|
||||
ibuf2 = IMB_allocImBuf(ibuf1->x, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags);
|
||||
if (ibuf2 == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
imb_half_y_no_alloc(ibuf2, ibuf1);
|
||||
|
||||
return ibuf2;
|
||||
}
|
||||
|
||||
/* pretty much specific functions which converts uchar <-> ushort but assumes
|
||||
* ushort range of 255*255 which is more convenient here
|
||||
*/
|
||||
MINLINE void straight_uchar_to_premul_ushort(ushort result[4], const uchar color[4])
|
||||
{
|
||||
ushort alpha = color[3];
|
||||
|
||||
result[0] = color[0] * alpha;
|
||||
result[1] = color[1] * alpha;
|
||||
result[2] = color[2] * alpha;
|
||||
result[3] = alpha * 256;
|
||||
}
|
||||
|
||||
MINLINE void premul_ushort_to_straight_uchar(uchar *result, const ushort color[4])
|
||||
{
|
||||
if (color[3] <= 255) {
|
||||
result[0] = unit_ushort_to_uchar(color[0]);
|
||||
result[1] = unit_ushort_to_uchar(color[1]);
|
||||
result[2] = unit_ushort_to_uchar(color[2]);
|
||||
result[3] = unit_ushort_to_uchar(color[3]);
|
||||
}
|
||||
else {
|
||||
ushort alpha = color[3] / 256;
|
||||
|
||||
result[0] = unit_ushort_to_uchar(ushort(color[0] / alpha * 256));
|
||||
result[1] = unit_ushort_to_uchar(ushort(color[1] / alpha * 256));
|
||||
result[2] = unit_ushort_to_uchar(ushort(color[2] / alpha * 256));
|
||||
result[3] = unit_ushort_to_uchar(color[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void imb_onehalf_no_alloc(ImBuf *ibuf2, ImBuf *ibuf1)
|
||||
{
|
||||
int x, y;
|
||||
const bool do_rect = (ibuf1->byte_buffer.data != nullptr);
|
||||
const bool do_float = (ibuf1->float_buffer.data != nullptr) &&
|
||||
(ibuf2->float_buffer.data != nullptr);
|
||||
|
||||
if (do_rect && (ibuf2->byte_buffer.data == nullptr)) {
|
||||
IMB_alloc_byte_pixels(ibuf2);
|
||||
}
|
||||
|
||||
if (ibuf1->x <= 1) {
|
||||
imb_half_y_no_alloc(ibuf2, ibuf1);
|
||||
return;
|
||||
}
|
||||
if (ibuf1->y <= 1) {
|
||||
imb_half_x_no_alloc(ibuf2, ibuf1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (do_rect) {
|
||||
uchar *cp1, *cp2, *dest;
|
||||
|
||||
cp1 = ibuf1->byte_buffer.data;
|
||||
dest = ibuf2->byte_buffer.data;
|
||||
|
||||
for (y = ibuf2->y; y > 0; y--) {
|
||||
cp2 = cp1 + (ibuf1->x << 2);
|
||||
for (x = ibuf2->x; x > 0; x--) {
|
||||
ushort p1i[8], p2i[8], desti[4];
|
||||
|
||||
straight_uchar_to_premul_ushort(p1i, cp1);
|
||||
straight_uchar_to_premul_ushort(p2i, cp2);
|
||||
straight_uchar_to_premul_ushort(p1i + 4, cp1 + 4);
|
||||
straight_uchar_to_premul_ushort(p2i + 4, cp2 + 4);
|
||||
|
||||
desti[0] = (uint(p1i[0]) + p2i[0] + p1i[4] + p2i[4]) >> 2;
|
||||
desti[1] = (uint(p1i[1]) + p2i[1] + p1i[5] + p2i[5]) >> 2;
|
||||
desti[2] = (uint(p1i[2]) + p2i[2] + p1i[6] + p2i[6]) >> 2;
|
||||
desti[3] = (uint(p1i[3]) + p2i[3] + p1i[7] + p2i[7]) >> 2;
|
||||
|
||||
premul_ushort_to_straight_uchar(dest, desti);
|
||||
|
||||
cp1 += 8;
|
||||
cp2 += 8;
|
||||
dest += 4;
|
||||
}
|
||||
cp1 = cp2;
|
||||
if (ibuf1->x & 1) {
|
||||
cp1 += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_float) {
|
||||
float *p1f, *p2f, *destf;
|
||||
|
||||
p1f = ibuf1->float_buffer.data;
|
||||
destf = ibuf2->float_buffer.data;
|
||||
for (y = ibuf2->y; y > 0; y--) {
|
||||
p2f = p1f + (ibuf1->x << 2);
|
||||
for (x = ibuf2->x; x > 0; x--) {
|
||||
destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]);
|
||||
destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]);
|
||||
destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]);
|
||||
destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]);
|
||||
p1f += 8;
|
||||
p2f += 8;
|
||||
destf += 4;
|
||||
}
|
||||
p1f = p2f;
|
||||
if (ibuf1->x & 1) {
|
||||
p1f += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImBuf *IMB_onehalf(ImBuf *ibuf1)
|
||||
{
|
||||
ImBuf *ibuf2;
|
||||
|
||||
if (ibuf1 == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (ibuf1->byte_buffer.data == nullptr && ibuf1->float_buffer.data == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (ibuf1->x <= 1) {
|
||||
return IMB_half_y(ibuf1);
|
||||
}
|
||||
if (ibuf1->y <= 1) {
|
||||
return IMB_half_x(ibuf1);
|
||||
}
|
||||
|
||||
ibuf2 = IMB_allocImBuf((ibuf1->x) / 2, (ibuf1->y) / 2, ibuf1->planes, ibuf1->flags);
|
||||
if (ibuf2 == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
imb_onehalf_no_alloc(ibuf2, ibuf1);
|
||||
|
||||
return ibuf2;
|
||||
}
|
||||
|
||||
static void alloc_scale_dst_buffers(
|
||||
const ImBuf *ibuf, uint newx, uint newy, uchar4 **r_dst_byte, float **r_dst_float)
|
||||
{
|
||||
|
||||
@@ -63,14 +63,12 @@
|
||||
.ima = NULL, \
|
||||
.stype = 0, \
|
||||
.flag = TEX_CHECKER_ODD | TEX_NO_CLAMP, \
|
||||
.imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA, \
|
||||
.imaflag = TEX_INTERPOL | TEX_USEALPHA, \
|
||||
.extend = TEX_REPEAT, \
|
||||
.cropxmin = 0.0, \
|
||||
.cropymin = 0.0, \
|
||||
.cropxmax = 1.0, \
|
||||
.cropymax = 1.0, \
|
||||
.texfilter = TXF_EWA, \
|
||||
.afmax = 8, \
|
||||
.xrepeat = 1, \
|
||||
.yrepeat = 1, \
|
||||
.sfra = 1, \
|
||||
|
||||
@@ -168,9 +168,6 @@ typedef struct Tex {
|
||||
short type, stype;
|
||||
|
||||
float cropxmin, cropymin, cropxmax, cropymax;
|
||||
int texfilter;
|
||||
/** Anisotropic filter maximum value, EWA -> max eccentricity, feline -> max probes. */
|
||||
int afmax;
|
||||
short xrepeat, yrepeat;
|
||||
short extend;
|
||||
|
||||
@@ -319,23 +316,12 @@ enum {
|
||||
enum {
|
||||
TEX_INTERPOL = 1 << 0,
|
||||
TEX_USEALPHA = 1 << 1,
|
||||
TEX_MIPMAP = 1 << 2,
|
||||
TEX_IMAROT = 1 << 4,
|
||||
TEX_CALCALPHA = 1 << 5,
|
||||
TEX_NORMALMAP = 1 << 11,
|
||||
TEX_GAUSS_MIP = 1 << 12,
|
||||
TEX_FILTER_MIN = 1 << 13,
|
||||
TEX_DERIVATIVEMAP = 1 << 14,
|
||||
};
|
||||
|
||||
/** #Tex::texfilter type. */
|
||||
enum {
|
||||
TXF_BOX = 0, /* Blender's old texture filtering method. */
|
||||
TXF_EWA = 1,
|
||||
TXF_FELINE = 2,
|
||||
TXF_AREA = 3,
|
||||
};
|
||||
|
||||
/** #Tex::flag bit-mask. */
|
||||
enum {
|
||||
TEX_COLORBAND = 1 << 0,
|
||||
|
||||
@@ -676,7 +676,7 @@ static void rna_Image_pixels_set(PointerRNA *ptr, const float *values)
|
||||
/* NOTE: Do update from the set() because typically pixels.foreach_set() is used to update
|
||||
* the values, and it does not invoke the update(). */
|
||||
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID | IB_MIPMAP_INVALID;
|
||||
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
|
||||
BKE_image_mark_dirty(ima, ibuf);
|
||||
if (!G.background) {
|
||||
BKE_image_free_gputextures(ima);
|
||||
|
||||
@@ -23,16 +23,6 @@
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#ifndef RNA_RUNTIME
|
||||
static const EnumPropertyItem texture_filter_items[] = {
|
||||
{TXF_BOX, "BOX", 0, "Box", ""},
|
||||
{TXF_EWA, "EWA", 0, "EWA", ""},
|
||||
{TXF_FELINE, "FELINE", 0, "FELINE", ""},
|
||||
{TXF_AREA, "AREA", 0, "Area", ""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
#endif
|
||||
|
||||
const EnumPropertyItem rna_enum_texture_type_items[] = {
|
||||
{0, "NONE", 0, "None", ""},
|
||||
{TEX_BLEND, "BLEND", ICON_TEXTURE, "Blend", "Procedural - create a ramp texture"},
|
||||
@@ -447,18 +437,6 @@ static void rna_Texture_use_nodes_update(bContext *C, PointerRNA *ptr)
|
||||
rna_Texture_nodes_update(CTX_data_main(C), CTX_data_scene(C), ptr);
|
||||
}
|
||||
|
||||
static void rna_ImageTexture_mipmap_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
Tex *tex = (Tex *)ptr->data;
|
||||
|
||||
if (value) {
|
||||
tex->imaflag |= TEX_MIPMAP;
|
||||
}
|
||||
else {
|
||||
tex->imaflag &= ~TEX_MIPMAP;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_texmapping(BlenderRNA *brna)
|
||||
@@ -694,57 +672,11 @@ static void rna_def_mtex(BlenderRNA *brna)
|
||||
static void rna_def_filter_common(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_property(srna, "use_mipmap", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "imaflag", TEX_MIPMAP);
|
||||
RNA_def_property_boolean_funcs(prop, nullptr, "rna_ImageTexture_mipmap_set");
|
||||
RNA_def_property_ui_text(prop, "MIP Map", "Use auto-generated MIP maps for the image");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_mipmap_gauss", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "imaflag", TEX_GAUSS_MIP);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "MIP Map Gaussian filter", "Use Gauss filter to sample down MIP maps");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop = RNA_def_property(srna, "filter_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, nullptr, "texfilter");
|
||||
RNA_def_property_enum_items(prop, texture_filter_items);
|
||||
RNA_def_property_ui_text(prop, "Filter", "Texture filter to use for sampling image");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop = RNA_def_property(srna, "filter_lightprobes", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "afmax");
|
||||
RNA_def_property_range(prop, 1, 256);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Filter Probes",
|
||||
"Maximum number of samples (higher gives less blur at distant/oblique angles, "
|
||||
"but is also slower)");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop = RNA_def_property(srna, "filter_eccentricity", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_int_sdna(prop, nullptr, "afmax");
|
||||
RNA_def_property_range(prop, 1, 256);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Filter Eccentricity",
|
||||
"Maximum eccentricity (higher gives less blur at distant/oblique angles, "
|
||||
"but is also slower)");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_filter_size_min", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "imaflag", TEX_FILTER_MIN);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Minimum Filter Size", "Use Filter Size as a minimal filter value in pixels");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
|
||||
prop = RNA_def_property(srna, "filter_size", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, nullptr, "filtersize");
|
||||
RNA_def_property_range(prop, 0.1, 50.0);
|
||||
RNA_def_property_ui_range(prop, 0.1, 50.0, 1, 2);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Filter Size", "Multiply the filter size used by MIP Map and Interpolation");
|
||||
RNA_def_property_ui_text(prop, "Filter Size", "Multiply the filter size used by interpolation");
|
||||
RNA_def_property_update(prop, 0, "rna_Texture_update");
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ static void texture_evaluate(Tex *tex, const float value[3], float r_color[4])
|
||||
TexResult texres = {0.0f};
|
||||
|
||||
/* TODO(sergey): always use color management now. */
|
||||
multitex_ext(tex, value, nullptr, nullptr, 1, &texres, 0, nullptr, true, false);
|
||||
multitex_ext(tex, value, &texres, 0, nullptr, true, false);
|
||||
|
||||
copy_v3_v3(r_color, texres.trgba);
|
||||
r_color[3] = texres.tin;
|
||||
|
||||
@@ -18,9 +18,6 @@ void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
|
||||
int ntreeTexExecTree(struct bNodeTree *ntree,
|
||||
struct TexResult *target,
|
||||
const float co[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
short thread,
|
||||
const struct Tex *tex,
|
||||
short which_output,
|
||||
|
||||
@@ -306,9 +306,6 @@ void ntreeTexEndExecTree(bNodeTreeExec *exec)
|
||||
int ntreeTexExecTree(bNodeTree *ntree,
|
||||
TexResult *target,
|
||||
const float co[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
const short thread,
|
||||
const Tex * /*tex*/,
|
||||
short which_output,
|
||||
@@ -322,9 +319,6 @@ int ntreeTexExecTree(bNodeTree *ntree,
|
||||
bNodeTreeExec *exec = ntree->runtime->execdata;
|
||||
|
||||
data.co = co;
|
||||
data.dxt = dxt;
|
||||
data.dyt = dyt;
|
||||
data.osatex = osatex;
|
||||
data.target = target;
|
||||
data.do_preview = preview;
|
||||
data.do_manage = true;
|
||||
|
||||
@@ -105,10 +105,7 @@ float tex_input_value(bNodeStack *in, TexParams *params, short thread)
|
||||
void params_from_cdata(TexParams *out, TexCallData *in)
|
||||
{
|
||||
out->co = in->co;
|
||||
out->dxt = in->dxt;
|
||||
out->dyt = in->dyt;
|
||||
out->previewco = in->co;
|
||||
out->osatex = in->osatex;
|
||||
out->cfra = in->cfra;
|
||||
out->mtex = in->mtex;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,9 @@ struct bNodeThreadStack;
|
||||
|
||||
struct TexCallData {
|
||||
TexResult *target;
|
||||
/* all float[3] */
|
||||
/* float[3] */
|
||||
const float *co;
|
||||
float *dxt, *dyt;
|
||||
|
||||
int osatex;
|
||||
bool do_preview;
|
||||
bool do_manage;
|
||||
short thread;
|
||||
@@ -39,10 +37,8 @@ struct TexCallData {
|
||||
|
||||
struct TexParams {
|
||||
const float *co;
|
||||
float *dxt, *dyt;
|
||||
const float *previewco;
|
||||
int cfra;
|
||||
int osatex;
|
||||
|
||||
/* optional. we don't really want these here, but image
|
||||
* textures need to do mapping & color correction */
|
||||
|
||||
@@ -45,8 +45,7 @@ static void do_proc(float *result,
|
||||
TexResult texres;
|
||||
int textype;
|
||||
|
||||
textype = multitex_nodes(
|
||||
tex, p->co, p->dxt, p->dyt, p->osatex, &texres, thread, 0, p->mtex, nullptr);
|
||||
textype = multitex_nodes(tex, p->co, &texres, thread, 0, p->mtex, nullptr);
|
||||
|
||||
if (textype & TEX_RGB) {
|
||||
copy_v4_v4(result, texres.trgba);
|
||||
|
||||
@@ -48,22 +48,16 @@ static void rotate(float new_co[3], float a, const float ax[3], const float co[3
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float new_co[3], new_dxt[3], new_dyt[3], a, ax[3];
|
||||
float new_co[3], a, ax[3];
|
||||
|
||||
a = tex_input_value(in[1], p, thread);
|
||||
tex_input_vec(ax, in[2], p, thread);
|
||||
|
||||
rotate(new_co, a, ax, p->co);
|
||||
if (p->osatex) {
|
||||
rotate(new_dxt, a, ax, p->dxt);
|
||||
rotate(new_dyt, a, ax, p->dyt);
|
||||
}
|
||||
|
||||
{
|
||||
TexParams np = *p;
|
||||
np.co = new_co;
|
||||
np.dxt = new_dxt;
|
||||
np.dyt = new_dyt;
|
||||
tex_input_rgba(out, in[0], &np, thread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,20 +23,14 @@ static blender::bke::bNodeSocketTemplate outputs[] = {
|
||||
|
||||
static void colorfn(float *out, TexParams *p, bNode * /*node*/, bNodeStack **in, short thread)
|
||||
{
|
||||
float scale[3], new_co[3], new_dxt[3], new_dyt[3];
|
||||
float scale[3], new_co[3];
|
||||
TexParams np = *p;
|
||||
|
||||
np.co = new_co;
|
||||
np.dxt = new_dxt;
|
||||
np.dyt = new_dyt;
|
||||
|
||||
tex_input_vec(scale, in[1], p, thread);
|
||||
|
||||
mul_v3_v3v3(new_co, p->co, scale);
|
||||
if (p->osatex) {
|
||||
mul_v3_v3v3(new_dxt, p->dxt, scale);
|
||||
mul_v3_v3v3(new_dyt, p->dyt, scale);
|
||||
}
|
||||
|
||||
tex_input_rgba(out, in[0], &np, thread);
|
||||
}
|
||||
|
||||
@@ -33,17 +33,9 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
Tex *nodetex = (Tex *)node->id;
|
||||
static float red[] = {1, 0, 0, 1};
|
||||
static float white[] = {1, 1, 1, 1};
|
||||
float co[3], dxt[3], dyt[3];
|
||||
float co[3];
|
||||
|
||||
copy_v3_v3(co, p->co);
|
||||
if (p->osatex) {
|
||||
copy_v3_v3(dxt, p->dxt);
|
||||
copy_v3_v3(dyt, p->dyt);
|
||||
}
|
||||
else {
|
||||
zero_v3(dxt);
|
||||
zero_v3(dyt);
|
||||
}
|
||||
|
||||
if (node->custom2 || node->runtime->need_exec == 0) {
|
||||
/* this node refers to its own texture tree! */
|
||||
@@ -57,8 +49,7 @@ static void colorfn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
|
||||
tex_input_rgba(col1, in[0], p, thread);
|
||||
tex_input_rgba(col2, in[1], p, thread);
|
||||
|
||||
textype = multitex_nodes(
|
||||
nodetex, co, dxt, dyt, p->osatex, &texres, thread, 0, p->mtex, nullptr);
|
||||
textype = multitex_nodes(nodetex, co, &texres, thread, 0, p->mtex, nullptr);
|
||||
|
||||
if (textype & TEX_RGB) {
|
||||
copy_v4_v4(out, texres.trgba);
|
||||
|
||||
@@ -97,9 +97,6 @@ struct TexResult {
|
||||
*/
|
||||
int multitex_ext(struct Tex *tex,
|
||||
const float texvec[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
struct TexResult *texres,
|
||||
short thread,
|
||||
struct ImagePool *pool,
|
||||
@@ -127,9 +124,6 @@ int multitex_ext_safe(struct Tex *tex,
|
||||
*/
|
||||
int multitex_nodes(struct Tex *tex,
|
||||
const float texvec[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
struct TexResult *texres,
|
||||
short thread,
|
||||
short which_output,
|
||||
|
||||
@@ -1601,11 +1601,6 @@ static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
|
||||
ibuf->userflags |= IB_RECT_INVALID;
|
||||
}
|
||||
|
||||
if (ibuf->mipmap[0]) {
|
||||
ibuf->userflags |= IB_MIPMAP_INVALID;
|
||||
IMB_free_mipmaps(ibuf);
|
||||
}
|
||||
|
||||
if (ibuf->userdata) {
|
||||
if (userdata->displacement_buffer) {
|
||||
MEM_freeN(userdata->displacement_buffer);
|
||||
|
||||
@@ -68,15 +68,6 @@ struct TexResult;
|
||||
|
||||
/* `texture_image.cc` */
|
||||
|
||||
int imagewraposa(struct Tex *tex,
|
||||
struct Image *ima,
|
||||
struct ImBuf *ibuf,
|
||||
const float texvec[3],
|
||||
const float DXT[2],
|
||||
const float DYT[2],
|
||||
struct TexResult *texres,
|
||||
struct ImagePool *pool,
|
||||
bool skip_load_image);
|
||||
int imagewrap(struct Tex *tex,
|
||||
struct Image *ima,
|
||||
const float texvec[3],
|
||||
|
||||
@@ -644,10 +644,6 @@ static void boxsample(ImBuf *ibuf,
|
||||
struct afdata_t {
|
||||
float dxt[2], dyt[2];
|
||||
int intpol, extflag;
|
||||
/* feline only */
|
||||
float majrad, minrad, theta;
|
||||
int iProbes;
|
||||
float dusc, dvsc;
|
||||
};
|
||||
|
||||
/* this only used here to make it easier to pass extend flags as single int */
|
||||
@@ -720,68 +716,6 @@ static int ibuf_get_color_clip(float col[4], ImBuf *ibuf, int x, int y, int extf
|
||||
return clip;
|
||||
}
|
||||
|
||||
/* as above + bilerp */
|
||||
static int ibuf_get_color_clip_bilerp(
|
||||
float col[4], ImBuf *ibuf, float u, float v, int intpol, int extflag)
|
||||
{
|
||||
if (intpol) {
|
||||
float c00[4], c01[4], c10[4], c11[4];
|
||||
const float ufl = floorf(u -= 0.5f), vfl = floorf(v -= 0.5f);
|
||||
const float uf = u - ufl, vf = v - vfl;
|
||||
const float w00 = (1.0f - uf) * (1.0f - vf), w10 = uf * (1.0f - vf), w01 = (1.0f - uf) * vf,
|
||||
w11 = uf * vf;
|
||||
const int x1 = int(ufl), y1 = int(vfl), x2 = x1 + 1, y2 = y1 + 1;
|
||||
int clip = ibuf_get_color_clip(c00, ibuf, x1, y1, extflag);
|
||||
clip |= ibuf_get_color_clip(c10, ibuf, x2, y1, extflag);
|
||||
clip |= ibuf_get_color_clip(c01, ibuf, x1, y2, extflag);
|
||||
clip |= ibuf_get_color_clip(c11, ibuf, x2, y2, extflag);
|
||||
col[0] = w00 * c00[0] + w10 * c10[0] + w01 * c01[0] + w11 * c11[0];
|
||||
col[1] = w00 * c00[1] + w10 * c10[1] + w01 * c01[1] + w11 * c11[1];
|
||||
col[2] = w00 * c00[2] + w10 * c10[2] + w01 * c01[2] + w11 * c11[2];
|
||||
col[3] = clip ? 0.0f : w00 * c00[3] + w10 * c10[3] + w01 * c01[3] + w11 * c11[3];
|
||||
return clip;
|
||||
}
|
||||
return ibuf_get_color_clip(col, ibuf, int(u), int(v), extflag);
|
||||
}
|
||||
|
||||
static void area_sample(TexResult *texr, ImBuf *ibuf, float fx, float fy, const afdata_t *AFD)
|
||||
{
|
||||
int xs, ys, clip = 0;
|
||||
float tc[4], xsd, ysd, cw = 0.0f;
|
||||
const float ux = ibuf->x * AFD->dxt[0], uy = ibuf->y * AFD->dxt[1];
|
||||
const float vx = ibuf->x * AFD->dyt[0], vy = ibuf->y * AFD->dyt[1];
|
||||
int xsam = int(0.5f * sqrtf(ux * ux + uy * uy) + 0.5f);
|
||||
int ysam = int(0.5f * sqrtf(vx * vx + vy * vy) + 0.5f);
|
||||
const int minsam = AFD->intpol ? 2 : 4;
|
||||
xsam = std::clamp(xsam, minsam, ibuf->x * 2);
|
||||
ysam = std::clamp(ysam, minsam, ibuf->y * 2);
|
||||
xsd = 1.0f / xsam;
|
||||
ysd = 1.0f / ysam;
|
||||
texr->trgba[0] = texr->trgba[1] = texr->trgba[2] = texr->trgba[3] = 0.0f;
|
||||
for (ys = 0; ys < ysam; ys++) {
|
||||
for (xs = 0; xs < xsam; xs++) {
|
||||
const float su = (xs + ((ys & 1) + 0.5f) * 0.5f) * xsd - 0.5f;
|
||||
const float sv = (ys + ((xs & 1) + 0.5f) * 0.5f) * ysd - 0.5f;
|
||||
const float pu = fx + su * AFD->dxt[0] + sv * AFD->dyt[0];
|
||||
const float pv = fy + su * AFD->dxt[1] + sv * AFD->dyt[1];
|
||||
const int out = ibuf_get_color_clip_bilerp(
|
||||
tc, ibuf, pu * ibuf->x, pv * ibuf->y, AFD->intpol, AFD->extflag);
|
||||
clip |= out;
|
||||
cw += out ? 0.0f : 1.0f;
|
||||
texr->trgba[0] += tc[0];
|
||||
texr->trgba[1] += tc[1];
|
||||
texr->trgba[2] += tc[2];
|
||||
texr->trgba[3] += texr->talpha ? tc[3] : 0.0f;
|
||||
}
|
||||
}
|
||||
xsd *= ysd;
|
||||
texr->trgba[0] *= xsd;
|
||||
texr->trgba[1] *= xsd;
|
||||
texr->trgba[2] *= xsd;
|
||||
/* clipping can be ignored if alpha used, texr->trgba[3] already includes filtered edge */
|
||||
texr->trgba[3] = texr->talpha ? texr->trgba[3] * xsd : (clip ? cw * xsd : 1.0f);
|
||||
}
|
||||
|
||||
struct ReadEWAData {
|
||||
ImBuf *ibuf;
|
||||
const afdata_t *AFD;
|
||||
@@ -811,885 +745,8 @@ static void ewa_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, const afd
|
||||
texr->trgba);
|
||||
}
|
||||
|
||||
static void feline_eval(TexResult *texr, ImBuf *ibuf, float fx, float fy, const afdata_t *AFD)
|
||||
{
|
||||
const int maxn = AFD->iProbes - 1;
|
||||
const float ll = ((AFD->majrad == AFD->minrad) ? 2.0f * AFD->majrad :
|
||||
2.0f * (AFD->majrad - AFD->minrad)) /
|
||||
(maxn ? float(maxn) : 1.0f);
|
||||
float du = maxn ? cosf(AFD->theta) * ll : 0.0f;
|
||||
float dv = maxn ? sinf(AFD->theta) * ll : 0.0f;
|
||||
// const float D = -0.5f*(du*du + dv*dv) / (AFD->majrad*AFD->majrad);
|
||||
const float D = (EWA_MAXIDX + 1) * 0.25f * (du * du + dv * dv) / (AFD->majrad * AFD->majrad);
|
||||
float d; /* TXF alpha: `cw = 0.0f`. */
|
||||
int n; /* TXF alpha: `clip = 0`. */
|
||||
/* Have to use same scaling for du/dv here as for Ux/Vx/Uy/Vy (*after* D is calculated.) */
|
||||
du *= AFD->dusc;
|
||||
dv *= AFD->dvsc;
|
||||
d = texr->trgba[0] = texr->trgba[2] = texr->trgba[1] = texr->trgba[3] = 0.0f;
|
||||
for (n = -maxn; n <= maxn; n += 2) {
|
||||
float tc[4];
|
||||
const float hn = n * 0.5f;
|
||||
const float u = fx + hn * du, v = fy + hn * dv;
|
||||
/* Can use ewa table here too. */
|
||||
#if 0
|
||||
const float wt = expf(n * n * D);
|
||||
#else
|
||||
const float wt = EWA_WTS[int(n * n * D)];
|
||||
#endif
|
||||
/* `const int out =` */ ibuf_get_color_clip_bilerp(
|
||||
tc, ibuf, ibuf->x * u, ibuf->y * v, AFD->intpol, AFD->extflag);
|
||||
/* TXF alpha: `clip |= out;`
|
||||
* TXF alpha: `cw += out ? 0.0f : wt;` */
|
||||
texr->trgba[0] += tc[0] * wt;
|
||||
texr->trgba[1] += tc[1] * wt;
|
||||
texr->trgba[2] += tc[2] * wt;
|
||||
texr->trgba[3] += texr->talpha ? tc[3] * wt : 0.0f;
|
||||
d += wt;
|
||||
}
|
||||
|
||||
d = 1.0f / d;
|
||||
texr->trgba[0] *= d;
|
||||
texr->trgba[1] *= d;
|
||||
texr->trgba[2] *= d;
|
||||
/* Clipping can be ignored if alpha used, `texr->trgba[3]` already includes filtered edge */
|
||||
texr->trgba[3] = texr->talpha ? texr->trgba[3] * d :
|
||||
1.0f; /* TXF alpha: `(clip ? cw*d : 1.0f);` */
|
||||
}
|
||||
#undef EWA_MAXIDX
|
||||
|
||||
static void alpha_clip_aniso(const ImBuf *ibuf,
|
||||
float minx,
|
||||
float miny,
|
||||
float maxx,
|
||||
float maxy,
|
||||
int extflag,
|
||||
TexResult *texres)
|
||||
{
|
||||
float alphaclip;
|
||||
rctf rf;
|
||||
|
||||
/* TXF alpha: we're doing the same alpha-clip here as box-sample, but I'm doubting
|
||||
* if this is actually correct for the all the filtering algorithms. */
|
||||
|
||||
if (!ELEM(extflag, TXC_REPT, TXC_EXTD)) {
|
||||
rf.xmin = minx * (ibuf->x);
|
||||
rf.xmax = maxx * (ibuf->x);
|
||||
rf.ymin = miny * (ibuf->y);
|
||||
rf.ymax = maxy * (ibuf->y);
|
||||
|
||||
alphaclip = clipx_rctf(&rf, 0.0, float(ibuf->x));
|
||||
alphaclip *= clipy_rctf(&rf, 0.0, float(ibuf->y));
|
||||
alphaclip = max_ff(alphaclip, 0.0f);
|
||||
|
||||
if (alphaclip != 1.0f) {
|
||||
/* Pre-multiply it all. */
|
||||
texres->trgba[0] *= alphaclip;
|
||||
texres->trgba[1] *= alphaclip;
|
||||
texres->trgba[2] *= alphaclip;
|
||||
texres->trgba[3] *= alphaclip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void image_mipmap_test(Tex *tex, ImBuf *ibuf)
|
||||
{
|
||||
if (tex->imaflag & TEX_MIPMAP) {
|
||||
if (ibuf->mipmap[0] && (ibuf->userflags & IB_MIPMAP_INVALID)) {
|
||||
BLI_thread_lock(LOCK_IMAGE);
|
||||
if (ibuf->userflags & IB_MIPMAP_INVALID) {
|
||||
IMB_remakemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
|
||||
ibuf->userflags &= ~IB_MIPMAP_INVALID;
|
||||
}
|
||||
BLI_thread_unlock(LOCK_IMAGE);
|
||||
}
|
||||
if (ibuf->mipmap[0] == nullptr) {
|
||||
BLI_thread_lock(LOCK_IMAGE);
|
||||
if (ibuf->mipmap[0] == nullptr) {
|
||||
IMB_makemipmap(ibuf, tex->imaflag & TEX_GAUSS_MIP);
|
||||
}
|
||||
BLI_thread_unlock(LOCK_IMAGE);
|
||||
}
|
||||
/* if no mipmap could be made, fall back on non-mipmap render */
|
||||
if (ibuf->mipmap[0] == nullptr) {
|
||||
tex->imaflag &= ~TEX_MIPMAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int imagewraposa_aniso(Tex *tex,
|
||||
Image *ima,
|
||||
ImBuf *ibuf,
|
||||
const float texvec[3],
|
||||
float dxt[2],
|
||||
float dyt[2],
|
||||
TexResult *texres,
|
||||
ImagePool *pool,
|
||||
const bool skip_load_image)
|
||||
{
|
||||
TexResult texr;
|
||||
float fx, fy, minx, maxx, miny, maxy;
|
||||
float maxd;
|
||||
int curmap, retval, intpol, extflag = 0;
|
||||
afdata_t AFD;
|
||||
|
||||
void (*filterfunc)(TexResult *, ImBuf *, float, float, const afdata_t *);
|
||||
switch (tex->texfilter) {
|
||||
case TXF_EWA:
|
||||
filterfunc = ewa_eval;
|
||||
break;
|
||||
case TXF_FELINE:
|
||||
filterfunc = feline_eval;
|
||||
break;
|
||||
case TXF_AREA:
|
||||
default:
|
||||
filterfunc = area_sample;
|
||||
}
|
||||
|
||||
texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f;
|
||||
|
||||
retval = TEX_RGB;
|
||||
|
||||
/* quick tests */
|
||||
if (ibuf == nullptr && ima == nullptr) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (ima) { /* hack for icon render */
|
||||
if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
|
||||
return retval;
|
||||
}
|
||||
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
|
||||
}
|
||||
|
||||
if ((ibuf == nullptr) ||
|
||||
((ibuf->byte_buffer.data == nullptr) && (ibuf->float_buffer.data == nullptr)))
|
||||
{
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (ima) {
|
||||
ima->flag |= IMA_USED_FOR_RENDER;
|
||||
}
|
||||
|
||||
/* mipmap test */
|
||||
image_mipmap_test(tex, ibuf);
|
||||
|
||||
if (ima) {
|
||||
if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
|
||||
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
|
||||
texres->talpha = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
texr.talpha = texres->talpha;
|
||||
|
||||
if (tex->imaflag & TEX_IMAROT) {
|
||||
fy = texvec[0];
|
||||
fx = texvec[1];
|
||||
}
|
||||
else {
|
||||
fx = texvec[0];
|
||||
fy = texvec[1];
|
||||
}
|
||||
|
||||
/* pixel coordinates */
|
||||
minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
|
||||
maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
|
||||
miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
|
||||
maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
|
||||
|
||||
/* tex_sharper has been removed */
|
||||
minx = (maxx - minx) * 0.5f;
|
||||
miny = (maxy - miny) * 0.5f;
|
||||
|
||||
if (tex->imaflag & TEX_FILTER_MIN) {
|
||||
/* Make sure the filtersize is minimal in pixels
|
||||
* (normal, ref map can have miniature pixel dx/dy). */
|
||||
const float addval = (0.5f * tex->filtersize) / float(std::min(ibuf->x, ibuf->y));
|
||||
minx = std::max(addval, minx);
|
||||
miny = std::max(addval, miny);
|
||||
}
|
||||
else if (tex->filtersize != 1.0f) {
|
||||
minx *= tex->filtersize;
|
||||
miny *= tex->filtersize;
|
||||
dxt[0] *= tex->filtersize;
|
||||
dxt[1] *= tex->filtersize;
|
||||
dyt[0] *= tex->filtersize;
|
||||
dyt[1] *= tex->filtersize;
|
||||
}
|
||||
|
||||
if (tex->imaflag & TEX_IMAROT) {
|
||||
float t;
|
||||
std::swap(minx, miny);
|
||||
/* must rotate dxt/dyt 90 deg
|
||||
* yet another blender problem is that swapping X/Y axes (or any tex projection switches)
|
||||
* should do something similar, but it doesn't, it only swaps coords,
|
||||
* so filter area will be incorrect in those cases. */
|
||||
t = dxt[0];
|
||||
dxt[0] = dxt[1];
|
||||
dxt[1] = -t;
|
||||
t = dyt[0];
|
||||
dyt[0] = dyt[1];
|
||||
dyt[1] = -t;
|
||||
}
|
||||
|
||||
/* side faces of unit-cube */
|
||||
minx = (minx > 0.25f) ? 0.25f : ((minx < 1e-5f) ? 1e-5f : minx);
|
||||
miny = (miny > 0.25f) ? 0.25f : ((miny < 1e-5f) ? 1e-5f : miny);
|
||||
|
||||
/* repeat and clip */
|
||||
|
||||
if (tex->extend == TEX_REPEAT) {
|
||||
if ((tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) == (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) {
|
||||
extflag = TXC_EXTD;
|
||||
}
|
||||
else if (tex->flag & TEX_REPEAT_XMIR) {
|
||||
extflag = TXC_XMIR;
|
||||
}
|
||||
else if (tex->flag & TEX_REPEAT_YMIR) {
|
||||
extflag = TXC_YMIR;
|
||||
}
|
||||
else {
|
||||
extflag = TXC_REPT;
|
||||
}
|
||||
}
|
||||
else if (tex->extend == TEX_EXTEND) {
|
||||
extflag = TXC_EXTD;
|
||||
}
|
||||
|
||||
if (tex->extend == TEX_CHECKER) {
|
||||
int xs = int(floorf(fx)), ys = int(floorf(fy));
|
||||
/* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
|
||||
if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
|
||||
fx -= xs;
|
||||
fy -= ys;
|
||||
}
|
||||
else if ((tex->flag & TEX_CHECKER_ODD) == 0 && (tex->flag & TEX_CHECKER_EVEN) == 0) {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
else {
|
||||
int xs1 = int(floorf(fx - minx));
|
||||
int ys1 = int(floorf(fy - miny));
|
||||
int xs2 = int(floorf(fx + minx));
|
||||
int ys2 = int(floorf(fy + miny));
|
||||
if ((xs1 != xs2) || (ys1 != ys2)) {
|
||||
if (tex->flag & TEX_CHECKER_ODD) {
|
||||
fx -= ((xs1 + ys) & 1) ? xs2 : xs1;
|
||||
fy -= ((ys1 + xs) & 1) ? ys2 : ys1;
|
||||
}
|
||||
if (tex->flag & TEX_CHECKER_EVEN) {
|
||||
fx -= ((xs1 + ys) & 1) ? xs1 : xs2;
|
||||
fy -= ((ys1 + xs) & 1) ? ys1 : ys2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((tex->flag & TEX_CHECKER_ODD) == 0 && ((xs + ys) & 1) == 0) {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
if ((tex->flag & TEX_CHECKER_EVEN) == 0 && (xs + ys) & 1) {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
fx -= xs;
|
||||
fy -= ys;
|
||||
}
|
||||
}
|
||||
/* scale around center, (0.5, 0.5) */
|
||||
if (tex->checkerdist < 1.0f) {
|
||||
const float omcd = 1.0f / (1.0f - tex->checkerdist);
|
||||
fx = (fx - 0.5f) * omcd + 0.5f;
|
||||
fy = (fy - 0.5f) * omcd + 0.5f;
|
||||
minx *= omcd;
|
||||
miny *= omcd;
|
||||
}
|
||||
}
|
||||
|
||||
if (tex->extend == TEX_CLIPCUBE) {
|
||||
if ((fx + minx) < 0.0f || (fy + miny) < 0.0f || (fx - minx) > 1.0f || (fy - miny) > 1.0f ||
|
||||
texvec[2] < -1.0f || texvec[2] > 1.0f)
|
||||
{
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
else if (ELEM(tex->extend, TEX_CLIP, TEX_CHECKER)) {
|
||||
if ((fx + minx) < 0.0f || (fy + miny) < 0.0f || (fx - minx) > 1.0f || (fy - miny) > 1.0f) {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tex->extend == TEX_EXTEND) {
|
||||
fx = (fx > 1.0f) ? 1.0f : ((fx < 0.0f) ? 0.0f : fx);
|
||||
fy = (fy > 1.0f) ? 1.0f : ((fy < 0.0f) ? 0.0f : fy);
|
||||
}
|
||||
else {
|
||||
fx -= floorf(fx);
|
||||
fy -= floorf(fy);
|
||||
}
|
||||
}
|
||||
|
||||
intpol = tex->imaflag & TEX_INTERPOL;
|
||||
|
||||
/* struct common data */
|
||||
copy_v2_v2(AFD.dxt, dxt);
|
||||
copy_v2_v2(AFD.dyt, dyt);
|
||||
AFD.intpol = intpol;
|
||||
AFD.extflag = extflag;
|
||||
|
||||
/* NOTE(@brecht): added stupid clamping here, large dx/dy can give very large
|
||||
* filter sizes which take ages to render, it may be better to do this
|
||||
* more intelligently later in the code .. probably it's not noticeable */
|
||||
if (AFD.dxt[0] * AFD.dxt[0] + AFD.dxt[1] * AFD.dxt[1] > 2.0f * 2.0f) {
|
||||
mul_v2_fl(AFD.dxt, 2.0f / len_v2(AFD.dxt));
|
||||
}
|
||||
if (AFD.dyt[0] * AFD.dyt[0] + AFD.dyt[1] * AFD.dyt[1] > 2.0f * 2.0f) {
|
||||
mul_v2_fl(AFD.dyt, 2.0f / len_v2(AFD.dyt));
|
||||
}
|
||||
|
||||
/* choice: */
|
||||
if (tex->imaflag & TEX_MIPMAP) {
|
||||
ImBuf *previbuf, *curibuf;
|
||||
float levf;
|
||||
int maxlev;
|
||||
ImBuf *mipmaps[IMB_MIPMAP_LEVELS + 1];
|
||||
|
||||
/* Modify ellipse minor axis if too eccentric, use for area sampling as well
|
||||
* scaling `dxt/dyt` as done in PBRT is not the same
|
||||
* (as in `ewa_eval()`, scale by `sqrt(ibuf->x)` to maximize precision). */
|
||||
const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
|
||||
const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
|
||||
const float A = Vx * Vx + Vy * Vy;
|
||||
const float B = -2.0f * (Ux * Vx + Uy * Vy);
|
||||
const float C = Ux * Ux + Uy * Uy;
|
||||
const float F = A * C - B * B * 0.25f;
|
||||
float a, b, th, ecc;
|
||||
BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
|
||||
if (tex->texfilter == TXF_FELINE) {
|
||||
float fProbes;
|
||||
a *= ff;
|
||||
b *= ff;
|
||||
a = max_ff(a, 1.0f);
|
||||
b = max_ff(b, 1.0f);
|
||||
fProbes = 2.0f * (a / b) - 1.0f;
|
||||
AFD.iProbes = round_fl_to_int(fProbes);
|
||||
AFD.iProbes = std::min(AFD.iProbes, tex->afmax);
|
||||
if (AFD.iProbes < fProbes) {
|
||||
b = 2.0f * a / float(AFD.iProbes + 1);
|
||||
}
|
||||
AFD.majrad = a / ff;
|
||||
AFD.minrad = b / ff;
|
||||
AFD.theta = th;
|
||||
AFD.dusc = 1.0f / ff;
|
||||
AFD.dvsc = ff / float(ibuf->y);
|
||||
}
|
||||
else { /* EWA & area */
|
||||
if (ecc > float(tex->afmax)) {
|
||||
b = a / float(tex->afmax);
|
||||
}
|
||||
b *= ff;
|
||||
}
|
||||
maxd = max_ff(b, 1e-8f);
|
||||
levf = float(M_LOG2E) * logf(maxd);
|
||||
|
||||
curmap = 0;
|
||||
maxlev = 1;
|
||||
mipmaps[0] = ibuf;
|
||||
while (curmap < IMB_MIPMAP_LEVELS) {
|
||||
mipmaps[curmap + 1] = ibuf->mipmap[curmap];
|
||||
if (ibuf->mipmap[curmap]) {
|
||||
maxlev++;
|
||||
}
|
||||
curmap++;
|
||||
}
|
||||
|
||||
/* mipmap level */
|
||||
if (levf < 0.0f) { /* original image only */
|
||||
previbuf = curibuf = mipmaps[0];
|
||||
levf = 0.0f;
|
||||
}
|
||||
else if (levf >= maxlev - 1) {
|
||||
previbuf = curibuf = mipmaps[maxlev - 1];
|
||||
levf = 0.0f;
|
||||
if (tex->texfilter == TXF_FELINE) {
|
||||
AFD.iProbes = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const int lev = isnan(levf) ? 0 : int(levf);
|
||||
curibuf = mipmaps[lev];
|
||||
previbuf = mipmaps[lev + 1];
|
||||
levf -= floorf(levf);
|
||||
}
|
||||
|
||||
/* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
|
||||
filterfunc(texres, curibuf, fx, fy, &AFD);
|
||||
if (previbuf != curibuf) { /* interpolate */
|
||||
filterfunc(&texr, previbuf, fx, fy, &AFD);
|
||||
texres->trgba[0] += levf * (texr.trgba[0] - texres->trgba[0]);
|
||||
texres->trgba[1] += levf * (texr.trgba[1] - texres->trgba[1]);
|
||||
texres->trgba[2] += levf * (texr.trgba[2] - texres->trgba[2]);
|
||||
texres->trgba[3] += levf * (texr.trgba[3] - texres->trgba[3]);
|
||||
}
|
||||
|
||||
if (tex->texfilter != TXF_EWA) {
|
||||
alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
|
||||
}
|
||||
}
|
||||
else { /* no mipmap */
|
||||
/* filter functions take care of interpolation themselves, no need to modify dxt/dyt here */
|
||||
if (tex->texfilter == TXF_FELINE) {
|
||||
const float ff = sqrtf(ibuf->x), q = ibuf->y / ff;
|
||||
const float Ux = dxt[0] * ff, Vx = dxt[1] * q, Uy = dyt[0] * ff, Vy = dyt[1] * q;
|
||||
const float A = Vx * Vx + Vy * Vy;
|
||||
const float B = -2.0f * (Ux * Vx + Uy * Vy);
|
||||
const float C = Ux * Ux + Uy * Uy;
|
||||
const float F = A * C - B * B * 0.25f;
|
||||
float a, b, th, ecc, fProbes;
|
||||
BLI_ewa_imp2radangle(A, B, C, F, &a, &b, &th, &ecc);
|
||||
a *= ff;
|
||||
b *= ff;
|
||||
a = max_ff(a, 1.0f);
|
||||
b = max_ff(b, 1.0f);
|
||||
fProbes = 2.0f * (a / b) - 1.0f;
|
||||
/* no limit to number of Probes here */
|
||||
AFD.iProbes = round_fl_to_int(fProbes);
|
||||
if (AFD.iProbes < fProbes) {
|
||||
b = 2.0f * a / float(AFD.iProbes + 1);
|
||||
}
|
||||
AFD.majrad = a / ff;
|
||||
AFD.minrad = b / ff;
|
||||
AFD.theta = th;
|
||||
AFD.dusc = 1.0f / ff;
|
||||
AFD.dvsc = ff / float(ibuf->y);
|
||||
}
|
||||
filterfunc(texres, ibuf, fx, fy, &AFD);
|
||||
if (tex->texfilter != TXF_EWA) {
|
||||
alpha_clip_aniso(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, extflag, texres);
|
||||
}
|
||||
}
|
||||
|
||||
if (tex->imaflag & TEX_CALCALPHA) {
|
||||
texres->trgba[3] = texres->tin = texres->trgba[3] *
|
||||
max_fff(texres->trgba[0], texres->trgba[1], texres->trgba[2]);
|
||||
}
|
||||
else {
|
||||
texres->tin = texres->trgba[3];
|
||||
}
|
||||
if (tex->flag & TEX_NEGALPHA) {
|
||||
texres->trgba[3] = 1.0f - texres->trgba[3];
|
||||
}
|
||||
|
||||
/* de-pre-multiply, this is being pre-multiplied in shade_input_do_shade()
|
||||
* TXF: this currently does not (yet?) work properly, destroys edge AA in clip/checker mode,
|
||||
* so for now commented out also disabled in #imagewraposa()
|
||||
* to be able to compare results with blender's default texture filtering */
|
||||
|
||||
/* NOTE(@brecht): tried to fix this, see "TXF alpha" comments. */
|
||||
|
||||
/* do not de-pre-multiply for generated alpha, it is already in straight */
|
||||
if (texres->trgba[3] != 1.0f && texres->trgba[3] > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
|
||||
fx = 1.0f / texres->trgba[3];
|
||||
texres->trgba[0] *= fx;
|
||||
texres->trgba[1] *= fx;
|
||||
texres->trgba[2] *= fx;
|
||||
}
|
||||
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
|
||||
BRICONTRGB;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int imagewraposa(Tex *tex,
|
||||
Image *ima,
|
||||
ImBuf *ibuf,
|
||||
const float texvec[3],
|
||||
const float DXT[2],
|
||||
const float DYT[2],
|
||||
TexResult *texres,
|
||||
ImagePool *pool,
|
||||
const bool skip_load_image)
|
||||
{
|
||||
TexResult texr;
|
||||
float fx, fy, minx, maxx, miny, maxy, dx, dy, dxt[2], dyt[2];
|
||||
float maxd, pixsize;
|
||||
int curmap, retval, imaprepeat, imapextend;
|
||||
|
||||
/* TXF: since dxt/dyt might be modified here and since they might be needed after imagewraposa()
|
||||
* call, make a local copy here so that original vecs remain untouched. */
|
||||
copy_v2_v2(dxt, DXT);
|
||||
copy_v2_v2(dyt, DYT);
|
||||
|
||||
/* anisotropic filtering */
|
||||
if (tex->texfilter != TXF_BOX) {
|
||||
return imagewraposa_aniso(tex, ima, ibuf, texvec, dxt, dyt, texres, pool, skip_load_image);
|
||||
}
|
||||
|
||||
texres->tin = texres->trgba[3] = texres->trgba[0] = texres->trgba[1] = texres->trgba[2] = 0.0f;
|
||||
|
||||
retval = TEX_RGB;
|
||||
|
||||
/* quick tests */
|
||||
if (ibuf == nullptr && ima == nullptr) {
|
||||
return retval;
|
||||
}
|
||||
if (ima) {
|
||||
|
||||
/* hack for icon render */
|
||||
if (skip_load_image && !BKE_image_has_loaded_ibuf(ima)) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
ibuf = BKE_image_pool_acquire_ibuf(ima, &tex->iuser, pool);
|
||||
|
||||
ima->flag |= IMA_USED_FOR_RENDER;
|
||||
}
|
||||
if (ibuf == nullptr || (ibuf->byte_buffer.data == nullptr && ibuf->float_buffer.data == nullptr))
|
||||
{
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* mipmap test */
|
||||
image_mipmap_test(tex, ibuf);
|
||||
|
||||
if (ima) {
|
||||
if ((tex->imaflag & TEX_USEALPHA) && (ima->alpha_mode != IMA_ALPHA_IGNORE)) {
|
||||
if ((tex->imaflag & TEX_CALCALPHA) == 0) {
|
||||
texres->talpha = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
texr.talpha = texres->talpha;
|
||||
|
||||
if (tex->imaflag & TEX_IMAROT) {
|
||||
fy = texvec[0];
|
||||
fx = texvec[1];
|
||||
}
|
||||
else {
|
||||
fx = texvec[0];
|
||||
fy = texvec[1];
|
||||
}
|
||||
|
||||
/* pixel coordinates */
|
||||
|
||||
minx = min_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
|
||||
maxx = max_fff(dxt[0], dyt[0], dxt[0] + dyt[0]);
|
||||
miny = min_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
|
||||
maxy = max_fff(dxt[1], dyt[1], dxt[1] + dyt[1]);
|
||||
|
||||
/* tex_sharper has been removed */
|
||||
minx = (maxx - minx) / 2.0f;
|
||||
miny = (maxy - miny) / 2.0f;
|
||||
|
||||
if (tex->imaflag & TEX_FILTER_MIN) {
|
||||
/* Make sure the filtersize is minimal in pixels
|
||||
* (normal, ref map can have miniature pixel dx/dy). */
|
||||
float addval = (0.5f * tex->filtersize) / float(std::min(ibuf->x, ibuf->y));
|
||||
|
||||
minx = std::max(addval, minx);
|
||||
miny = std::max(addval, miny);
|
||||
}
|
||||
else if (tex->filtersize != 1.0f) {
|
||||
minx *= tex->filtersize;
|
||||
miny *= tex->filtersize;
|
||||
|
||||
dxt[0] *= tex->filtersize;
|
||||
dxt[1] *= tex->filtersize;
|
||||
dyt[0] *= tex->filtersize;
|
||||
dyt[1] *= tex->filtersize;
|
||||
}
|
||||
|
||||
if (tex->imaflag & TEX_IMAROT) {
|
||||
std::swap(minx, miny);
|
||||
}
|
||||
|
||||
if (minx > 0.25f) {
|
||||
minx = 0.25f;
|
||||
}
|
||||
else if (minx < 0.00001f) {
|
||||
minx = 0.00001f; /* side faces of unit-cube */
|
||||
}
|
||||
if (miny > 0.25f) {
|
||||
miny = 0.25f;
|
||||
}
|
||||
else if (miny < 0.00001f) {
|
||||
miny = 0.00001f;
|
||||
}
|
||||
|
||||
/* repeat and clip */
|
||||
imaprepeat = (tex->extend == TEX_REPEAT);
|
||||
imapextend = (tex->extend == TEX_EXTEND);
|
||||
|
||||
if (tex->extend == TEX_REPEAT) {
|
||||
if (tex->flag & (TEX_REPEAT_XMIR | TEX_REPEAT_YMIR)) {
|
||||
imaprepeat = 0;
|
||||
imapextend = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tex->extend == TEX_CHECKER) {
|
||||
int xs, ys, xs1, ys1, xs2, ys2, boundary;
|
||||
|
||||
xs = int(floor(fx));
|
||||
ys = int(floor(fy));
|
||||
|
||||
/* both checkers available, no boundary exceptions, checkerdist will eat aliasing */
|
||||
if ((tex->flag & TEX_CHECKER_ODD) && (tex->flag & TEX_CHECKER_EVEN)) {
|
||||
fx -= xs;
|
||||
fy -= ys;
|
||||
}
|
||||
else if ((tex->flag & TEX_CHECKER_ODD) == 0 && (tex->flag & TEX_CHECKER_EVEN) == 0) {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
else {
|
||||
|
||||
xs1 = int(floor(fx - minx));
|
||||
ys1 = int(floor(fy - miny));
|
||||
xs2 = int(floor(fx + minx));
|
||||
ys2 = int(floor(fy + miny));
|
||||
boundary = (xs1 != xs2) || (ys1 != ys2);
|
||||
|
||||
if (boundary == 0) {
|
||||
if ((tex->flag & TEX_CHECKER_ODD) == 0) {
|
||||
if ((xs + ys) & 1) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
if ((tex->flag & TEX_CHECKER_EVEN) == 0) {
|
||||
if ((xs + ys) & 1) {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
fx -= xs;
|
||||
fy -= ys;
|
||||
}
|
||||
else {
|
||||
if (tex->flag & TEX_CHECKER_ODD) {
|
||||
if ((xs1 + ys) & 1) {
|
||||
fx -= xs2;
|
||||
}
|
||||
else {
|
||||
fx -= xs1;
|
||||
}
|
||||
|
||||
if ((ys1 + xs) & 1) {
|
||||
fy -= ys2;
|
||||
}
|
||||
else {
|
||||
fy -= ys1;
|
||||
}
|
||||
}
|
||||
if (tex->flag & TEX_CHECKER_EVEN) {
|
||||
if ((xs1 + ys) & 1) {
|
||||
fx -= xs1;
|
||||
}
|
||||
else {
|
||||
fx -= xs2;
|
||||
}
|
||||
|
||||
if ((ys1 + xs) & 1) {
|
||||
fy -= ys1;
|
||||
}
|
||||
else {
|
||||
fy -= ys2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* scale around center, (0.5, 0.5) */
|
||||
if (tex->checkerdist < 1.0f) {
|
||||
fx = (fx - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
|
||||
fy = (fy - 0.5f) / (1.0f - tex->checkerdist) + 0.5f;
|
||||
minx /= (1.0f - tex->checkerdist);
|
||||
miny /= (1.0f - tex->checkerdist);
|
||||
}
|
||||
}
|
||||
|
||||
if (tex->extend == TEX_CLIPCUBE) {
|
||||
if (fx + minx < 0.0f || fy + miny < 0.0f || fx - minx > 1.0f || fy - miny > 1.0f ||
|
||||
texvec[2] < -1.0f || texvec[2] > 1.0f)
|
||||
{
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
else if (ELEM(tex->extend, TEX_CLIP, TEX_CHECKER)) {
|
||||
if (fx + minx < 0.0f || fy + miny < 0.0f || fx - minx > 1.0f || fy - miny > 1.0f) {
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (imapextend) {
|
||||
if (fx > 1.0f) {
|
||||
fx = 1.0f;
|
||||
}
|
||||
else if (fx < 0.0f) {
|
||||
fx = 0.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fx > 1.0f) {
|
||||
fx -= int(fx);
|
||||
}
|
||||
else if (fx < 0.0f) {
|
||||
fx += 1 - int(fx);
|
||||
}
|
||||
}
|
||||
|
||||
if (imapextend) {
|
||||
if (fy > 1.0f) {
|
||||
fy = 1.0f;
|
||||
}
|
||||
else if (fy < 0.0f) {
|
||||
fy = 0.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fy > 1.0f) {
|
||||
fy -= int(fy);
|
||||
}
|
||||
else if (fy < 0.0f) {
|
||||
fy += 1 - int(fy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Choice: */
|
||||
if (tex->imaflag & TEX_MIPMAP) {
|
||||
ImBuf *previbuf, *curibuf;
|
||||
|
||||
dx = minx;
|
||||
dy = miny;
|
||||
maxd = max_ff(dx, dy);
|
||||
maxd = std::min(maxd, 0.5f);
|
||||
|
||||
pixsize = 1.0f / float(std::min(ibuf->x, ibuf->y));
|
||||
|
||||
curmap = 0;
|
||||
previbuf = curibuf = ibuf;
|
||||
while (curmap < IMB_MIPMAP_LEVELS && ibuf->mipmap[curmap]) {
|
||||
if (maxd < pixsize) {
|
||||
break;
|
||||
}
|
||||
previbuf = curibuf;
|
||||
curibuf = ibuf->mipmap[curmap];
|
||||
pixsize = 1.0f / float(std::min(curibuf->x, curibuf->y));
|
||||
curmap++;
|
||||
}
|
||||
|
||||
if (previbuf != curibuf || (tex->imaflag & TEX_INTERPOL)) {
|
||||
/* sample at least 1 pixel */
|
||||
minx = std::max(minx, 0.5f / ibuf->x);
|
||||
miny = std::max(miny, 0.5f / ibuf->y);
|
||||
}
|
||||
|
||||
maxx = fx + minx;
|
||||
minx = fx - minx;
|
||||
maxy = fy + miny;
|
||||
miny = fy - miny;
|
||||
|
||||
boxsample(curibuf, minx, miny, maxx, maxy, texres, imaprepeat, imapextend);
|
||||
|
||||
if (previbuf != curibuf) { /* interpolate */
|
||||
boxsample(previbuf, minx, miny, maxx, maxy, &texr, imaprepeat, imapextend);
|
||||
|
||||
fx = 2.0f * (pixsize - maxd) / pixsize;
|
||||
|
||||
if (fx >= 1.0f) {
|
||||
texres->trgba[3] = texr.trgba[3];
|
||||
texres->trgba[2] = texr.trgba[2];
|
||||
texres->trgba[1] = texr.trgba[1];
|
||||
texres->trgba[0] = texr.trgba[0];
|
||||
}
|
||||
else {
|
||||
fy = 1.0f - fx;
|
||||
texres->trgba[2] = fy * texres->trgba[2] + fx * texr.trgba[2];
|
||||
texres->trgba[1] = fy * texres->trgba[1] + fx * texr.trgba[1];
|
||||
texres->trgba[0] = fy * texres->trgba[0] + fx * texr.trgba[0];
|
||||
texres->trgba[3] = fy * texres->trgba[3] + fx * texr.trgba[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const int intpol = tex->imaflag & TEX_INTERPOL;
|
||||
if (intpol) {
|
||||
/* sample 1 pixel minimum */
|
||||
minx = std::max(minx, 0.5f / ibuf->x);
|
||||
miny = std::max(miny, 0.5f / ibuf->y);
|
||||
}
|
||||
|
||||
boxsample(ibuf, fx - minx, fy - miny, fx + minx, fy + miny, texres, imaprepeat, imapextend);
|
||||
}
|
||||
|
||||
if (tex->imaflag & TEX_CALCALPHA) {
|
||||
texres->trgba[3] = texres->tin = texres->trgba[3] *
|
||||
max_fff(texres->trgba[0], texres->trgba[1], texres->trgba[2]);
|
||||
}
|
||||
else {
|
||||
texres->tin = texres->trgba[3];
|
||||
}
|
||||
|
||||
if (tex->flag & TEX_NEGALPHA) {
|
||||
texres->trgba[3] = 1.0f - texres->trgba[3];
|
||||
}
|
||||
|
||||
/* de-pre-multiply, this is being pre-multiplied in shade_input_do_shade() */
|
||||
/* do not de-pre-multiply for generated alpha, it is already in straight */
|
||||
if (texres->trgba[3] != 1.0f && texres->trgba[3] > 1e-4f && !(tex->imaflag & TEX_CALCALPHA)) {
|
||||
mul_v3_fl(texres->trgba, 1.0f / texres->trgba[3]);
|
||||
}
|
||||
|
||||
if (ima) {
|
||||
BKE_image_pool_release_ibuf(ima, ibuf, pool);
|
||||
}
|
||||
|
||||
BRICONTRGB;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void image_sample(
|
||||
Image *ima, float fx, float fy, float dx, float dy, float result[4], ImagePool *pool)
|
||||
{
|
||||
|
||||
@@ -618,18 +618,17 @@ static int cubemap_glob(const float n[3], float x, float y, float z, float *adr1
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void do_2d_mapping(
|
||||
const MTex *mtex, float texvec[3], const float n[3], float dxt[3], float dyt[3])
|
||||
static void do_2d_mapping(const MTex *mtex, float texvec[3], const float n[3])
|
||||
{
|
||||
Tex *tex;
|
||||
float fx, fy, fac1, area[8];
|
||||
int ok, proj, areaflag = 0, wrap;
|
||||
float fx, fy, fac1;
|
||||
int wrap;
|
||||
|
||||
/* #MTex variables localized, only cube-map doesn't cooperate yet. */
|
||||
wrap = mtex->mapping;
|
||||
tex = mtex->tex;
|
||||
|
||||
if (!(dxt && dyt)) {
|
||||
{
|
||||
|
||||
if (wrap == MTEX_FLAT) {
|
||||
fx = (texvec[0] + 1.0f) / 2.0f;
|
||||
@@ -692,177 +691,6 @@ static void do_2d_mapping(
|
||||
fy = tex->cropymin + fy * fac1;
|
||||
}
|
||||
|
||||
texvec[0] = fx;
|
||||
texvec[1] = fy;
|
||||
}
|
||||
else {
|
||||
|
||||
if (wrap == MTEX_FLAT) {
|
||||
fx = (texvec[0] + 1.0f) / 2.0f;
|
||||
fy = (texvec[1] + 1.0f) / 2.0f;
|
||||
dxt[0] /= 2.0f;
|
||||
dxt[1] /= 2.0f;
|
||||
dxt[2] /= 2.0f;
|
||||
dyt[0] /= 2.0f;
|
||||
dyt[1] /= 2.0f;
|
||||
dyt[2] /= 2.0f;
|
||||
}
|
||||
else if (ELEM(wrap, MTEX_TUBE, MTEX_SPHERE)) {
|
||||
/* exception: the seam behind (y<0.0) */
|
||||
ok = 1;
|
||||
if (texvec[1] <= 0.0f) {
|
||||
fx = texvec[0] + dxt[0];
|
||||
fy = texvec[0] + dyt[0];
|
||||
if (fx >= 0.0f && fy >= 0.0f && texvec[0] >= 0.0f) {
|
||||
/* pass */
|
||||
}
|
||||
else if (fx <= 0.0f && fy <= 0.0f && texvec[0] <= 0.0f) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (wrap == MTEX_TUBE) {
|
||||
map_to_tube(area, area + 1, texvec[0], texvec[1], texvec[2]);
|
||||
map_to_tube(
|
||||
area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
|
||||
map_to_tube(
|
||||
area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
|
||||
}
|
||||
else {
|
||||
map_to_sphere(area, area + 1, texvec[0], texvec[1], texvec[2]);
|
||||
map_to_sphere(
|
||||
area + 2, area + 3, texvec[0] + dxt[0], texvec[1] + dxt[1], texvec[2] + dxt[2]);
|
||||
map_to_sphere(
|
||||
area + 4, area + 5, texvec[0] + dyt[0], texvec[1] + dyt[1], texvec[2] + dyt[2]);
|
||||
}
|
||||
areaflag = 1;
|
||||
}
|
||||
else {
|
||||
if (wrap == MTEX_TUBE) {
|
||||
map_to_tube(&fx, &fy, texvec[0], texvec[1], texvec[2]);
|
||||
}
|
||||
else {
|
||||
map_to_sphere(&fx, &fy, texvec[0], texvec[1], texvec[2]);
|
||||
}
|
||||
dxt[0] /= 2.0f;
|
||||
dxt[1] /= 2.0f;
|
||||
dyt[0] /= 2.0f;
|
||||
dyt[1] /= 2.0f;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
proj = cubemap_glob(n, texvec[0], texvec[1], texvec[2], &fx, &fy);
|
||||
|
||||
if (proj == 1) {
|
||||
std::swap(dxt[1], dxt[2]);
|
||||
std::swap(dyt[1], dyt[2]);
|
||||
}
|
||||
else if (proj == 2) {
|
||||
float f1 = dxt[0], f2 = dyt[0];
|
||||
dxt[0] = dxt[1];
|
||||
dyt[0] = dyt[1];
|
||||
dxt[1] = dxt[2];
|
||||
dyt[1] = dyt[2];
|
||||
dxt[2] = f1;
|
||||
dyt[2] = f2;
|
||||
}
|
||||
|
||||
dxt[0] *= 0.5f;
|
||||
dxt[1] *= 0.5f;
|
||||
dxt[2] *= 0.5f;
|
||||
|
||||
dyt[0] *= 0.5f;
|
||||
dyt[1] *= 0.5f;
|
||||
dyt[2] *= 0.5f;
|
||||
}
|
||||
|
||||
/* If area, then recalculate `dxt[]` and `dyt[]` */
|
||||
if (areaflag) {
|
||||
fx = area[0];
|
||||
fy = area[1];
|
||||
dxt[0] = area[2] - fx;
|
||||
dxt[1] = area[3] - fy;
|
||||
dyt[0] = area[4] - fx;
|
||||
dyt[1] = area[5] - fy;
|
||||
}
|
||||
|
||||
/* repeat */
|
||||
if (tex->extend == TEX_REPEAT) {
|
||||
float max = 1.0f;
|
||||
if (tex->xrepeat > 1) {
|
||||
float origf = fx *= tex->xrepeat;
|
||||
|
||||
/* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
|
||||
if (tex->texfilter == TXF_BOX) {
|
||||
if (fx > 1.0f) {
|
||||
fx -= int(fx);
|
||||
}
|
||||
else if (fx < 0.0f) {
|
||||
fx += 1 - int(fx);
|
||||
}
|
||||
|
||||
if (tex->flag & TEX_REPEAT_XMIR) {
|
||||
int orig = int(floor(origf));
|
||||
if (orig & 1) {
|
||||
fx = 1.0f - fx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
max = tex->xrepeat;
|
||||
|
||||
dxt[0] *= tex->xrepeat;
|
||||
dyt[0] *= tex->xrepeat;
|
||||
}
|
||||
if (tex->yrepeat > 1) {
|
||||
float origf = fy *= tex->yrepeat;
|
||||
|
||||
/* TXF: omit mirror here, see comments in do_material_tex() after do_2d_mapping() call */
|
||||
if (tex->texfilter == TXF_BOX) {
|
||||
if (fy > 1.0f) {
|
||||
fy -= int(fy);
|
||||
}
|
||||
else if (fy < 0.0f) {
|
||||
fy += 1 - int(fy);
|
||||
}
|
||||
|
||||
if (tex->flag & TEX_REPEAT_YMIR) {
|
||||
int orig = int(floor(origf));
|
||||
if (orig & 1) {
|
||||
fy = 1.0f - fy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
max = std::max<float>(max, tex->yrepeat);
|
||||
|
||||
dxt[1] *= tex->yrepeat;
|
||||
dyt[1] *= tex->yrepeat;
|
||||
}
|
||||
if (max != 1.0f) {
|
||||
dxt[2] *= max;
|
||||
dyt[2] *= max;
|
||||
}
|
||||
}
|
||||
/* crop */
|
||||
if (tex->cropxmin != 0.0f || tex->cropxmax != 1.0f) {
|
||||
fac1 = tex->cropxmax - tex->cropxmin;
|
||||
fx = tex->cropxmin + fx * fac1;
|
||||
dxt[0] *= fac1;
|
||||
dyt[0] *= fac1;
|
||||
}
|
||||
if (tex->cropymin != 0.0f || tex->cropymax != 1.0f) {
|
||||
fac1 = tex->cropymax - tex->cropymin;
|
||||
fy = tex->cropymin + fy * fac1;
|
||||
dxt[1] *= fac1;
|
||||
dyt[1] *= fac1;
|
||||
}
|
||||
|
||||
texvec[0] = fx;
|
||||
texvec[1] = fy;
|
||||
}
|
||||
@@ -872,9 +700,6 @@ static void do_2d_mapping(
|
||||
|
||||
static int multitex(Tex *tex,
|
||||
const float texvec[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
TexResult *texres,
|
||||
const short thread,
|
||||
const short which_output,
|
||||
@@ -890,18 +715,8 @@ static int multitex(Tex *tex,
|
||||
|
||||
if (use_nodes && tex->use_nodes && tex->nodetree) {
|
||||
const float cfra = 1.0f; /* This was only set for Blender Internal render before. */
|
||||
retval = ntreeTexExecTree(tex->nodetree,
|
||||
texres,
|
||||
texvec,
|
||||
dxt,
|
||||
dyt,
|
||||
osatex,
|
||||
thread,
|
||||
tex,
|
||||
which_output,
|
||||
cfra,
|
||||
texnode_preview,
|
||||
nullptr);
|
||||
retval = ntreeTexExecTree(
|
||||
tex->nodetree, texres, texvec, thread, tex, which_output, cfra, texnode_preview, nullptr);
|
||||
}
|
||||
else {
|
||||
switch (tex->type) {
|
||||
@@ -930,13 +745,7 @@ static int multitex(Tex *tex,
|
||||
retval = texnoise(tex, texres, thread);
|
||||
break;
|
||||
case TEX_IMAGE:
|
||||
if (osatex) {
|
||||
retval = imagewraposa(
|
||||
tex, tex->ima, nullptr, texvec, dxt, dyt, texres, pool, skip_load_image);
|
||||
}
|
||||
else {
|
||||
retval = imagewrap(tex, tex->ima, texvec, texres, pool, skip_load_image);
|
||||
}
|
||||
retval = imagewrap(tex, tex->ima, texvec, texres, pool, skip_load_image);
|
||||
if (tex->ima) {
|
||||
BKE_image_tag_time(tex->ima);
|
||||
}
|
||||
@@ -996,9 +805,6 @@ static int multitex(Tex *tex,
|
||||
|
||||
static int multitex_nodes_intern(Tex *tex,
|
||||
const float texvec[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
TexResult *texres,
|
||||
const short thread,
|
||||
short which_output,
|
||||
@@ -1025,12 +831,9 @@ static int multitex_nodes_intern(Tex *tex,
|
||||
float texvec_l[3];
|
||||
copy_v3_v3(texvec_l, texvec);
|
||||
/* we have mtex, use it for 2d mapping images only */
|
||||
do_2d_mapping(mtex, texvec_l, nullptr, dxt, dyt);
|
||||
do_2d_mapping(mtex, texvec_l, nullptr);
|
||||
retval = multitex(tex,
|
||||
texvec_l,
|
||||
dxt,
|
||||
dyt,
|
||||
osatex,
|
||||
texres,
|
||||
thread,
|
||||
which_output,
|
||||
@@ -1056,7 +859,7 @@ static int multitex_nodes_intern(Tex *tex,
|
||||
else {
|
||||
/* we don't have mtex, do default flat 2d projection */
|
||||
MTex localmtex;
|
||||
float texvec_l[3], dxt_l[3], dyt_l[3];
|
||||
float texvec_l[3];
|
||||
|
||||
localmtex.mapping = MTEX_FLAT;
|
||||
localmtex.tex = tex;
|
||||
@@ -1064,21 +867,10 @@ static int multitex_nodes_intern(Tex *tex,
|
||||
localmtex.texco = TEXCO_ORCO;
|
||||
|
||||
copy_v3_v3(texvec_l, texvec);
|
||||
if (dxt && dyt) {
|
||||
copy_v3_v3(dxt_l, dxt);
|
||||
copy_v3_v3(dyt_l, dyt);
|
||||
}
|
||||
else {
|
||||
zero_v3(dxt_l);
|
||||
zero_v3(dyt_l);
|
||||
}
|
||||
|
||||
do_2d_mapping(&localmtex, texvec_l, nullptr, dxt_l, dyt_l);
|
||||
do_2d_mapping(&localmtex, texvec_l, nullptr);
|
||||
retval = multitex(tex,
|
||||
texvec_l,
|
||||
dxt_l,
|
||||
dyt_l,
|
||||
osatex,
|
||||
texres,
|
||||
thread,
|
||||
which_output,
|
||||
@@ -1107,9 +899,6 @@ static int multitex_nodes_intern(Tex *tex,
|
||||
|
||||
return multitex(tex,
|
||||
texvec,
|
||||
dxt,
|
||||
dyt,
|
||||
osatex,
|
||||
texres,
|
||||
thread,
|
||||
which_output,
|
||||
@@ -1121,36 +910,18 @@ static int multitex_nodes_intern(Tex *tex,
|
||||
|
||||
int multitex_nodes(Tex *tex,
|
||||
const float texvec[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
TexResult *texres,
|
||||
const short thread,
|
||||
short which_output,
|
||||
const MTex *mtex,
|
||||
ImagePool *pool)
|
||||
{
|
||||
return multitex_nodes_intern(tex,
|
||||
texvec,
|
||||
dxt,
|
||||
dyt,
|
||||
osatex,
|
||||
texres,
|
||||
thread,
|
||||
which_output,
|
||||
mtex,
|
||||
pool,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true);
|
||||
return multitex_nodes_intern(
|
||||
tex, texvec, texres, thread, which_output, mtex, pool, true, false, false, true);
|
||||
}
|
||||
|
||||
int multitex_ext(Tex *tex,
|
||||
const float texvec[3],
|
||||
float dxt[3],
|
||||
float dyt[3],
|
||||
int osatex,
|
||||
TexResult *texres,
|
||||
const short thread,
|
||||
ImagePool *pool,
|
||||
@@ -1159,9 +930,6 @@ int multitex_ext(Tex *tex,
|
||||
{
|
||||
return multitex_nodes_intern(tex,
|
||||
texvec,
|
||||
dxt,
|
||||
dyt,
|
||||
osatex,
|
||||
texres,
|
||||
thread,
|
||||
0,
|
||||
@@ -1180,20 +948,8 @@ int multitex_ext_safe(Tex *tex,
|
||||
bool scene_color_manage,
|
||||
const bool skip_load_image)
|
||||
{
|
||||
return multitex_nodes_intern(tex,
|
||||
texvec,
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
texres,
|
||||
0,
|
||||
0,
|
||||
nullptr,
|
||||
pool,
|
||||
scene_color_manage,
|
||||
skip_load_image,
|
||||
false,
|
||||
false);
|
||||
return multitex_nodes_intern(
|
||||
tex, texvec, texres, 0, 0, nullptr, pool, scene_color_manage, skip_load_image, false, false);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
@@ -1293,7 +1049,7 @@ bool RE_texture_evaluate(const MTex *mtex,
|
||||
{
|
||||
Tex *tex;
|
||||
TexResult texr;
|
||||
float dxt[3], dyt[3], texvec[3];
|
||||
float texvec[3];
|
||||
int rgb;
|
||||
|
||||
tex = mtex->tex;
|
||||
@@ -1325,14 +1081,11 @@ bool RE_texture_evaluate(const MTex *mtex,
|
||||
|
||||
/* texture */
|
||||
if (tex->type == TEX_IMAGE) {
|
||||
do_2d_mapping(mtex, texvec, nullptr, dxt, dyt);
|
||||
do_2d_mapping(mtex, texvec, nullptr);
|
||||
}
|
||||
|
||||
rgb = multitex(tex,
|
||||
texvec,
|
||||
dxt,
|
||||
dyt,
|
||||
0,
|
||||
&texr,
|
||||
thread,
|
||||
mtex->which_output,
|
||||
|
||||
Reference in New Issue
Block a user