-
-
Save vividsnow/ae6b4eb17015f8749173 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void main (void) { | |
float d = distance(vec2(0.5), gl_PointCoord); | |
if (d >= 0.5) { discard; } | |
gl_FragColor = vec4(gl_Color.rgb, max(2 * (0.5 - d), 0) * gl_Color.a); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package Vz::Node::3d::Rotor; | |
use v5.16; | |
use Moo; | |
extends 'Vz::Node'; | |
use OpenGL ':all'; | |
use Math::SegmentedEnvelope 'env'; | |
use PDL; | |
use PDL::Constants qw(PI E I); | |
use PDL::Stats::TS; | |
use PDL::Image2D; | |
use AnyEvent; | |
use List::Util 'shuffle'; | |
use Time::HiRes qw'gettimeofday tv_interval'; | |
use Memoize; | |
use namespace::autoclean; | |
has qw(rotate is rw default), sub { pdl 0,0,0 }; | |
has qw(scale is rw default), sub { [1,1,1] }; | |
has qw(trail is rw default), sub { [1,1] }; | |
has qw(buf is rw lazy 1 default), sub { | |
my $self = shift; | |
(my $ar = OpenGL::Array->new($self->num_of_points * 16, GL_FLOAT))->bind(my $id = glGenBuffersARB_p(1)); # x y z r g b a s x 2 | |
glBufferDataARB_p(GL_ARRAY_BUFFER_ARB, $ar, GL_DYNAMIC_DRAW_ARB); | |
$id; | |
}; | |
has qw(point_size is rw default), sub { 40 }; | |
has qw(attenuation is rw default), sub { 0.73 }; | |
has qw(last_shape is rw default), sub { 0 }; | |
has qw(transit_smooth is rw default), sub { 1 }; | |
has qw(num_of_points is rw default), sub { 236 }; | |
has qw(shader is rw lazy 1 default), sub { shift->world->parent->tools->shader->make(qw'rotor trail') }; | |
has on_add => is => rw => default => sub { [ sub { | |
shift->create_shape; | |
} ] }; | |
has on_display => is => rw => default => sub { [ sub { | |
my $self = shift; | |
my $shader = $self->shader; | |
state $started = AE::now; | |
state $previous = 0; | |
my $now = AE::now - $started; | |
my $elapsed = $now - $previous; | |
$previous = $now; | |
glPushAttrib(GL_ENABLE_BIT|GL_POINT_BIT); | |
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); | |
glEnable(GL_POINT_SPRITE); | |
glEnable(GL_COLOR_MATERIAL); | |
glPushMatrix(); | |
glTranslatef(0,0,-1); | |
glScaled(@{$self->scale}); | |
$shader->enable; | |
glBindBufferARB(GL_ARRAY_BUFFER_ARB, $self->buf); | |
map glEnableClientState($_), GL_VERTEX_ARRAY, GL_COLOR_ARRAY; | |
glVertexPointer_c(3, GL_FLOAT,(my $stride = 4*8), 0); # 4 float size, 8 xyzsrgba | |
glEnableVertexAttribArrayARB(my $size_idx = $shader->attr('cur_size')); | |
glVertexAttribPointerARB_c($size_idx, 1, GL_FLOAT, GL_FALSE, $stride, (my $size_offset = 3*4)); | |
glColorPointer_c(4, GL_FLOAT, $stride, (my $color_offset = 4*4)); | |
glEnableVertexAttribArrayARB(my $next_pos_idx = $shader->attr('next_pos')); | |
glVertexAttribPointerARB_c($next_pos_idx, 3, GL_FLOAT, GL_FALSE, $stride, (my $next_shape = $self->num_of_points * $stride)); | |
glEnableVertexAttribArrayARB(my $next_size_idx = $shader->attr('next_size')); | |
glVertexAttribPointerARB_c($next_size_idx, 1, GL_FLOAT, GL_FALSE, $stride, $next_shape + $size_offset); | |
glEnableVertexAttribArrayARB(my $next_clr_idx = $shader->attr('next_clr')); | |
glVertexAttribPointerARB_c($next_clr_idx, 4, GL_FLOAT, GL_FALSE, $stride, $next_shape + $color_offset); | |
glPointParameterfvARB_p(GL_POINT_DISTANCE_ATTENUATION, 0, 0, $self->attenuation); | |
map { | |
glPushMatrix(); | |
glPointSize($self->point_size / sqrt sqrt $_); | |
glTranslatef(0,0,-0.5); | |
state $rot; | |
$rot = $self->rotate * $now % 1 * 360; # $fix + $now for smoothing | |
map glRotatef($rot->at($_), (0)x$_, 1, (0)x(2-$_)), 0..2; | |
glTranslatef(-0.5,-0.5,-0.5); | |
$shader->vec(f => cf => (1)x3, 1 / sqrt $_); | |
$shader->vec(f => morph => $self->morph_pos($now)); | |
glDrawArrays(GL_POINTS, 0, $self->num_of_points); | |
glPopMatrix(); | |
$now -= ($_ * $elapsed / $self->trail->[0]); | |
} 1..$self->trail->[1]; | |
map glDisableVertexAttribArrayARB($_), $size_idx, $next_pos_idx, $next_size_idx, $next_clr_idx; | |
map glDisableClientState($_), GL_VERTEX_ARRAY, GL_COLOR_ARRAY; | |
$shader->disable; | |
glPopMatrix(); | |
glPopAttrib(); | |
} ] }; | |
sub create_shape { | |
my ($self, $ind) = @_; | |
return do { | |
$self->create_rotate; | |
map $self->create_shape($_), 0..1; | |
} unless defined $ind; | |
my $t0 = [gettimeofday]; | |
my $complex = int(rand(2)); | |
my $eq_spaced = int(rand(2)); | |
my $points = $self->num_of_points; #int rand(300) + 100; | |
# my $vert = pdl(float, map { [ env(is_morph => 1)->table($points, $complex ? int(rand(3)+1) : 1) ] } 0..7)->transpose->flat; | |
my $vert = pdl(float, map { [ env(is_morph => 1)->table($points, $complex ? int(rand(3)+1) : 1) ] } 0..7); | |
equally_spaced_curve($vert->slice(':,0:2')) if $eq_spaced; | |
$vert = $vert->transpose->flat; | |
(my $data = OpenGL::Array->new_scalar(GL_FLOAT, $vert->get_dataref, $vert->dim(0)*4))->bind($self->buf); | |
#glBufferSubDataARB_c(GL_ARRAY_BUFFER_ARB, $ind*$vert->dim(0)*4, $vert->dim(0)*4, $data->ptr); | |
glBufferSubDataARB_p(GL_ARRAY_BUFFER_ARB, $ind*$vert->dim(0), $data); | |
# seems that *_p knows of type of $data, so offset should be in type elements, not bytes | |
say 'tooks to create ', $ind, ' ', tv_interval($t0); | |
} | |
sub create_rotate { | |
my $self = shift; | |
$self->set( | |
rotate => pdl(map { int(rand(2)) ? -1 : 1 } 1..3) * pdl(shuffle map { (4+rand(1.2))/2**$_ } 1, 4, 6), | |
scale => [ +(ones(3) + pdl(map { int(rand(2)) ? -1 : 1 } 1..3) * pdl(shuffle map 1/2**$_, (1..3)))->list ], | |
trail => [ 1 + int rand 9, 3 + int rand 7 ] | |
); | |
} | |
sub transit_rotate { | |
my ($self) = @_; | |
my $old_rot = $self->rotate; | |
my $df = pdl(map { int(rand(2)) ? -1 : 1 } 1..3) * pdl(shuffle map { (4+rand(1.2))/2**$_ } 1, 4, 6) - $old_rot; | |
my $k = 0; | |
$self->timer->add( rotate_transit => sub { | |
$k += $self->timer->rate; | |
$self->rotate($old_rot + $df*$k); | |
}, 1 ); | |
} | |
sub transit { | |
my ($self) = @_; | |
$self->timer->add( transit_begin => sub { | |
$self->transit_smooth(abs( $self->transit_smooth - 1/25 )); | |
}, 1, 0, sub { | |
$self->transit_smooth(0); | |
$self->create_shape(!$self->last_shape+0); | |
$self->timer->add( transit_end => sub { | |
$self->transit_smooth($self->transit_smooth + 1/25); | |
}, 1, 0, sub { | |
$self->transit_smooth(1); | |
$self->last_shape(!$self->last_shape+0); | |
}, 1/24); | |
}, 1/25); | |
} | |
sub morph_pos { | |
state $evaluator = memoize sub { | |
(sin($_[0])*0.5+0.5) * $_[1] + $_[2] * abs(1 - $_[1]); | |
}; | |
$evaluator->($_[1], $_[0]->transit_smooth, $_[0]->last_shape); | |
} | |
sub restart { shift->create_shape } | |
sub equally_spaced_curve { | |
my ($l, $points) = @_; | |
say 'make eq cureve'; | |
$points //= $l->dim(0); | |
my $start_vals = $l->slice('(0),:')->transpose; | |
$l -= $start_vals; | |
my $len_total = (my $df = $l->diff->pow(2)->transpose->sumover->sqrt->cumusumover)->at(-1); | |
my $positions = (zeroes(1)->append(ones($points-1)*$len_total/$points))->cumusumover; | |
my $smooth = 3 + int rand 5; | |
$l .= conv2d +(pdl(map { interpol($positions, $df, $l->slice(':,('.$_.')')) } 0..$l->dim(1)-1) + $start_vals)/5, ones(5), { Boundary => 'Reflect' }; | |
} | |
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
use v5.16; | |
use Vz; | |
my $vz = Vz->new; | |
$vz->add(camera => [ '3d_rotor' => { | |
init => sub { | |
my $self = shift; | |
$vz->window->bind_key(t => sub { $self->create_shape } ); | |
$vz->window->bind_key(r => sub { $self->transit_rotate } ); | |
$vz->window->bind_key(g => sub { $self->transit } ); | |
$vz->window->bind_key(v => sub { $self->trail->[0]-- } ); | |
$vz->window->bind_key(b => sub { $self->trail->[0]++ } ); | |
$vz->window->bind_key(n => sub { $self->trail->[1]-- } ); | |
$vz->window->bind_key(m => sub { $self->trail->[1]++ } ); | |
} | |
} ]); | |
$vz->play; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
uniform vec4 cf; | |
uniform float morph; | |
attribute vec3 next_pos; | |
attribute float next_size; | |
attribute vec4 next_clr; | |
attribute float cur_size; | |
void main(void) { | |
vec4 vert = mix(gl_Vertex, vec4(next_pos, gl_Vertex.w), morph); | |
gl_Position = gl_ModelViewProjectionMatrix * vert; | |
float dist = distance(gl_ModelViewMatrix * vert, vec3(0,0,1)); | |
vec4 color = mix(gl_Color, next_clr, morph); | |
gl_FrontColor = vec4(color.rgb, 1);//color.a * cf.a / dist | |
gl_PointSize = (0.1 + mix(cur_size, next_size, morph)) * gl_Point.size * sqrt(1.0 / (gl_Point.distanceQuadraticAttenuation * dist * dist)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment