GPv3: Tint and Color modifiers #117297
|
@ -80,7 +80,7 @@ void legacy_gpencil_frame_to_grease_pencil_drawing(const bGPDframe &gpf,
|
|||
SpanAttributeWriter<float> stroke_hardnesses = attributes.lookup_or_add_for_write_span<float>(
|
||||
"hardness", AttrDomain::Curve);
|
||||
SpanAttributeWriter<float> stroke_point_aspect_ratios =
|
||||
attributes.lookup_or_add_for_write_span<float>("point_aspect_ratio", AttrDomain::Curve);
|
||||
attributes.lookup_or_add_for_write_span<float>("aspect_ratio", AttrDomain::Curve);
|
||||
SpanAttributeWriter<float2> stroke_fill_translations =
|
||||
attributes.lookup_or_add_for_write_span<float2>("fill_translation", AttrDomain::Curve);
|
||||
SpanAttributeWriter<float> stroke_fill_rotations =
|
||||
|
|
|
@ -1189,7 +1189,7 @@ class NodeTreeMainUpdater {
|
|||
}
|
||||
|
||||
/* Used to generate new unique IDs if necessary. */
|
||||
RandomNumberGenerator rng(PIL_check_seconds_timer_i() & UINT_MAX);
|
||||
RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
|
||||
|
||||
Map<int32_t, bNestedNodePath> new_path_by_id;
|
||||
for (const bNestedNodePath &path : nested_node_paths) {
|
||||
|
|
|
@ -62,6 +62,8 @@
|
|||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "BIK_api.h"
|
||||
|
||||
#ifdef WITH_BULLET
|
||||
|
@ -3349,6 +3351,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
|
|||
}
|
||||
|
||||
/* clear baking flag */
|
||||
PTCacheID pid_eval;
|
||||
if (pid && cache) {
|
||||
cache->flag &= ~(PTCACHE_BAKING | PTCACHE_REDO_NEEDED);
|
||||
cache->flag |= PTCACHE_SIMULATION_VALID;
|
||||
|
@ -3356,7 +3359,13 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
|
|||
cache->flag |= PTCACHE_BAKED;
|
||||
/* write info file */
|
||||
if (cache->flag & PTCACHE_DISK_CACHE) {
|
||||
BKE_ptcache_write(pid, 0);
|
||||
ID *id = pid->owner_id;
|
||||
Object *ob = (GS(id->name) == ID_OB) ? reinterpret_cast<Object *>(id) : nullptr;
|
||||
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
ParticleSystem *psys = static_cast<ParticleSystem *>(pid->calldata);
|
||||
ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
|
||||
BKE_ptcache_id_from_particles(&pid_eval, ob_eval, psys_eval);
|
||||
BKE_ptcache_write(&pid_eval, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3386,7 +3395,13 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
|
|||
if (bake) {
|
||||
cache->flag |= PTCACHE_BAKED;
|
||||
if (cache->flag & PTCACHE_DISK_CACHE) {
|
||||
BKE_ptcache_write(pid, 0);
|
||||
ID *id = pid->owner_id;
|
||||
Object *ob = (GS(id->name) == ID_OB) ? reinterpret_cast<Object *>(id) : nullptr;
|
||||
Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
|
||||
ParticleSystem *psys = static_cast<ParticleSystem *>(pid->calldata);
|
||||
ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
|
||||
BKE_ptcache_id_from_particles(&pid_eval, ob_eval, psys_eval);
|
||||
BKE_ptcache_write(&pid_eval, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,12 @@ class RandomNumberGenerator {
|
|||
this->seed(seed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a random number generator with a somewhat random seed. This can be used when
|
||||
* determinism is not necessary or not desired.
|
||||
*/
|
||||
static RandomNumberGenerator from_random_seed();
|
||||
|
||||
/**
|
||||
* Set the seed for future random numbers.
|
||||
*/
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "BLI_strict_flags.h"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
extern "C" uchar BLI_noise_hash_uchar_512[512]; /* `noise.cc` */
|
||||
#define hash BLI_noise_hash_uchar_512
|
||||
|
||||
|
@ -363,6 +365,12 @@ void BLI_hammersley_2d_sequence(uint n, double *r)
|
|||
|
||||
namespace blender {
|
||||
|
||||
RandomNumberGenerator RandomNumberGenerator::from_random_seed()
|
||||
{
|
||||
const double time = PIL_check_seconds_timer() * 1000000.0;
|
||||
return RandomNumberGenerator(*reinterpret_cast<const uint32_t *>(&time));
|
||||
}
|
||||
|
||||
void RandomNumberGenerator::seed_random(uint32_t seed)
|
||||
{
|
||||
this->seed(seed + hash[seed & 255]);
|
||||
|
|
|
@ -12,6 +12,7 @@ void main()
|
|||
ivec2 output_size = max(imageSize(output_img), imageSize(mask_img));
|
||||
vec2 coordinates = (vec2(texel) + vec2(0.5)) / vec2(output_size);
|
||||
|
||||
float accumulated_mask = 0.0;
|
||||
vec4 accumulated_color = vec4(0.0);
|
||||
for (int i = 0; i < number_of_motion_blur_samples; i++) {
|
||||
mat3 homography_matrix = mat3(homography_matrices[i]);
|
||||
|
@ -25,11 +26,21 @@ void main()
|
|||
vec2 x_gradient = homography_matrix[0].xy / transformed_coordinates.z;
|
||||
vec2 y_gradient = homography_matrix[1].xy / transformed_coordinates.z;
|
||||
|
||||
accumulated_color += textureGrad(input_tx, projected_coordinates, x_gradient, y_gradient);
|
||||
vec4 sampled_color = textureGrad(input_tx, projected_coordinates, x_gradient, y_gradient);
|
||||
accumulated_color += sampled_color;
|
||||
|
||||
/* The plane mask is 1 if it is inside the plane and 0 otherwise. However, we use the alpha
|
||||
* value of the sampled color for pixels outside of the plane to utilize the anti-aliasing
|
||||
* effect of the anisotropic filtering. Therefore, the input_tx sampler should use anisotropic
|
||||
* filtering and be clamped to zero border color. */
|
||||
bool is_inside_plane = all(greaterThanEqual(projected_coordinates, vec2(0.0))) &&
|
||||
all(lessThanEqual(projected_coordinates, vec2(1.0)));
|
||||
accumulated_mask += is_inside_plane ? 1.0 : sampled_color.a;
|
||||
}
|
||||
|
||||
accumulated_mask /= number_of_motion_blur_samples;
|
||||
accumulated_color /= number_of_motion_blur_samples;
|
||||
|
||||
imageStore(output_img, texel, accumulated_color);
|
||||
imageStore(mask_img, texel, accumulated_color.aaaa);
|
||||
imageStore(mask_img, texel, vec4(accumulated_mask));
|
||||
}
|
||||
|
|
|
@ -54,12 +54,23 @@ vec3 gpencil_lighting(void)
|
|||
return clamp(light_accum, 0.0, 1e10);
|
||||
}
|
||||
|
||||
/* TODO: Remove this once we can render textures. */
|
||||
vec4 debug_texture(vec2 uv)
|
||||
{
|
||||
vec4 col = vec4(mod(uv.xy, 1.0), 0.0, 1.0);
|
||||
return col * min(length(uv.xy * 2 - 1), 1);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 col;
|
||||
if (flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_USE)) {
|
||||
bool premul = flag_test(gp_interp_flat.mat_flag, GP_STROKE_TEXTURE_PREMUL);
|
||||
col = texture_read_as_linearrgb(gpStrokeTexture, premul, gp_interp.uv);
|
||||
|
||||
/* TODO: Remove this once we can render textures. */
|
||||
/* Debug color. (Because textures are not yet implemented) */
|
||||
col = debug_texture(gp_interp.uv);
|
||||
}
|
||||
else if (flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_USE)) {
|
||||
bool use_clip = flag_test(gp_interp_flat.mat_flag, GP_FILL_TEXTURE_CLIP);
|
||||
|
|
|
@ -488,17 +488,24 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||
const VArray<float> opacities = info.drawing.opacities();
|
||||
const VArray<ColorGeometry4f> vertex_colors = *attributes.lookup_or_default<ColorGeometry4f>(
|
||||
"vertex_color", bke::AttrDomain::Point, ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
const VArray<float> rotations = *attributes.lookup_or_default<float>(
|
||||
"rotation", bke::AttrDomain::Point, 0.0f);
|
||||
/* Assumes that if the ".selection" attribute does not exist, all points are selected. */
|
||||
const VArray<float> selection_float = *attributes.lookup_or_default<float>(
|
||||
".selection", bke::AttrDomain::Point, true);
|
||||
const VArray<int8_t> start_caps = *attributes.lookup_or_default<int8_t>(
|
||||
"start_cap", bke::AttrDomain::Curve, GP_STROKE_CAP_TYPE_ROUND);
|
||||
const VArray<int8_t> end_caps = *attributes.lookup_or_default<int8_t>(
|
||||
"end_cap", bke::AttrDomain::Curve, GP_STROKE_CAP_TYPE_ROUND);
|
||||
"end_cap", bke::AttrDomain::Curve, 0);
|
||||
const VArray<float> stroke_hardnesses = *attributes.lookup_or_default<float>(
|
||||
"hardness", bke::AttrDomain::Curve, 1.0f);
|
||||
const VArray<float> stroke_point_aspect_ratios = *attributes.lookup_or_default<float>(
|
||||
"aspect_ratio", bke::AttrDomain::Curve, 1.0f);
|
||||
const VArray<ColorGeometry4f> stroke_fill_colors =
|
||||
*attributes.lookup_or_default<ColorGeometry4f>(
|
||||
"fill_color", bke::AttrDomain::Curve, ColorGeometry4f(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
const VArray<int> materials = *attributes.lookup_or_default<int>(
|
||||
"material_index", bke::AttrDomain::Curve, 0);
|
||||
const VArray<float> hardness = *attributes.lookup_or_default<float>(
|
||||
"hardness", bke::AttrDomain::Curve, 1.0f);
|
||||
const Span<uint3> triangles = info.drawing.triangles();
|
||||
const Span<int> verts_start_offsets = verts_start_offsets_per_visible_drawing[drawing_i];
|
||||
const Span<int> tris_start_offsets = tris_start_offsets_per_visible_drawing[drawing_i];
|
||||
|
@ -506,12 +513,15 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||
const IndexMask visible_strokes = ed::greasepencil::retrieve_visible_strokes(
|
||||
object, info.drawing, memory);
|
||||
|
||||
curves.ensure_evaluated_lengths();
|
||||
|
||||
auto populate_point = [&](IndexRange verts_range,
|
||||
int curve_i,
|
||||
int8_t start_cap,
|
||||
int8_t end_cap,
|
||||
int point_i,
|
||||
int idx,
|
||||
float length,
|
||||
GreasePencilStrokeVert &s_vert,
|
||||
GreasePencilColorVert &c_vert) {
|
||||
copy_v3_v3(s_vert.pos, positions[point_i]);
|
||||
|
@ -522,15 +532,14 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||
s_vert.stroke_id = verts_range.first();
|
||||
s_vert.mat = materials[curve_i] % GPENCIL_MATERIAL_BUFFER_LEN;
|
||||
|
||||
/* TODO: Populate rotation and aspect. */
|
||||
s_vert.packed_asp_hard_rot = pack_rotation_aspect_hardness(0.0f, 1.0f, hardness[curve_i]);
|
||||
/* TODO: Populate stroke UVs. */
|
||||
s_vert.u_stroke = 0;
|
||||
s_vert.packed_asp_hard_rot = pack_rotation_aspect_hardness(
|
||||
rotations[point_i], stroke_point_aspect_ratios[curve_i], stroke_hardnesses[curve_i]);
|
||||
s_vert.u_stroke = length;
|
||||
/* TODO: Populate fill UVs. */
|
||||
s_vert.uv_fill[0] = s_vert.uv_fill[1] = 0;
|
||||
|
||||
copy_v4_v4(c_vert.vcol, vertex_colors[point_i]);
|
||||
copy_v4_v4(c_vert.fcol, vertex_colors[point_i]);
|
||||
copy_v4_v4(c_vert.fcol, stroke_fill_colors[curve_i]);
|
||||
c_vert.fcol[3] = (int(c_vert.fcol[3] * 10000.0f) * 10.0f) + 1.0f;
|
||||
|
||||
int v_mat = (verts_range[idx] << GP_VERTEX_ID_SHIFT) | GP_IS_STROKE_VERTEX_BIT;
|
||||
|
@ -548,6 +557,8 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||
MutableSpan<GreasePencilStrokeVert> verts_slice = verts.slice(verts_range);
|
||||
MutableSpan<GreasePencilColorVert> cols_slice = cols.slice(verts_range);
|
||||
|
||||
const Span<float> lengths = curves.evaluated_lengths_for_curve(curve_i, is_cyclic);
|
||||
|
||||
/* First vertex is not drawn. */
|
||||
verts_slice.first().mat = -1;
|
||||
|
||||
|
@ -565,24 +576,28 @@ static void grease_pencil_geom_batch_ensure(Object &object,
|
|||
/* Write all the point attributes to the vertex buffers. Create a quad for each point. */
|
||||
for (const int i : IndexRange(points.size())) {
|
||||
const int idx = i + 1;
|
||||
const float length = (i >= 1) ? lengths[i - 1] : 0.0f;
|
||||
populate_point(verts_range,
|
||||
curve_i,
|
||||
start_caps[curve_i],
|
||||
end_caps[curve_i],
|
||||
points[i],
|
||||
idx,
|
||||
length,
|
||||
verts_slice[idx],
|
||||
cols_slice[idx]);
|
||||
}
|
||||
|
||||
if (is_cyclic) {
|
||||
const int idx = points.size() + 1;
|
||||
const float length = lengths[points.size() - 1];
|
||||
populate_point(verts_range,
|
||||
curve_i,
|
||||
start_caps[curve_i],
|
||||
end_caps[curve_i],
|
||||
points[0],
|
||||
idx,
|
||||
length,
|
||||
verts_slice[idx],
|
||||
cols_slice[idx]);
|
||||
}
|
||||
|
|
|
@ -179,9 +179,7 @@ struct AddOperationExecutor {
|
|||
return;
|
||||
}
|
||||
|
||||
const double time = PIL_check_seconds_timer() * 1000000.0;
|
||||
/* Use a pointer cast to avoid overflow warnings. */
|
||||
RandomNumberGenerator rng{*(uint32_t *)(&time)};
|
||||
RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
|
||||
|
||||
/* Sample points on the surface using one of multiple strategies. */
|
||||
Vector<float2> sampled_uvs;
|
||||
|
|
|
@ -164,8 +164,7 @@ struct DensityAddOperationExecutor {
|
|||
|
||||
Vector<float3> new_positions_cu;
|
||||
Vector<float2> new_uvs;
|
||||
const double time = PIL_check_seconds_timer() * 1000000.0;
|
||||
RandomNumberGenerator rng{*(uint32_t *)(&time)};
|
||||
RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
|
||||
|
||||
/* Find potential new curve root points. */
|
||||
if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE) {
|
||||
|
@ -634,7 +633,7 @@ struct DensitySubtractOperationExecutor {
|
|||
* strength. */
|
||||
Array<bool> allow_remove_curve(curves_->curves_num(), false);
|
||||
threading::parallel_for(curves_->curves_range(), 512, [&](const IndexRange range) {
|
||||
RandomNumberGenerator rng(int(PIL_check_seconds_timer() * 1000000.0));
|
||||
RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
|
||||
|
||||
for (const int curve_i : range) {
|
||||
if (!curves_to_keep[curve_i]) {
|
||||
|
@ -724,7 +723,7 @@ struct DensitySubtractOperationExecutor {
|
|||
* strength. */
|
||||
Array<bool> allow_remove_curve(curves_->curves_num(), false);
|
||||
threading::parallel_for(curves_->curves_range(), 512, [&](const IndexRange range) {
|
||||
RandomNumberGenerator rng(int(PIL_check_seconds_timer() * 1000000.0));
|
||||
RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
|
||||
|
||||
for (const int curve_i : range) {
|
||||
if (!curves_to_keep[curve_i]) {
|
||||
|
|
|
@ -884,7 +884,7 @@ static void update_nested_node_refs_after_moving_nodes_into_group(
|
|||
const Map<int32_t, int32_t> &node_identifier_map)
|
||||
{
|
||||
/* Update nested node references in the parent and child node tree. */
|
||||
RandomNumberGenerator rng(PIL_check_seconds_timer_i() & UINT_MAX);
|
||||
RandomNumberGenerator rng = RandomNumberGenerator::from_random_seed();
|
||||
Vector<bNestedNodeRef> new_nested_node_refs;
|
||||
/* Keep all nested node references that were in the group before. */
|
||||
for (const bNestedNodeRef &ref : group.nested_node_refs_span()) {
|
||||
|
|
Loading…
Reference in New Issue