1- "use strict" ;
1+ "use strict"
22
33import { FragmentShader , VertexShader , ShaderProgram } from './shader.js' ;
44import { QuadPrimitive } from './quad-primitive.js' ;
@@ -21,120 +21,14 @@ export class GL {
2121 this . gl = canvas . getContext ( "webgl2" ) ;
2222 this . gl . get_super = ( ) => this ;
2323
24+ this . render_hooks = [ ] ;
25+
2426 this . objects = [ ] ;
2527
2628 this . projection_matrix = Matrix . identity ( ) ;
2729 this . view_matrix = Matrix . identity ( ) ;
2830
2931 this . camera_position = new Vector ( 0 , 0 , 0 , 1 ) ;
30- this . mouse_position = new Vector ( 0 , 0 , 0 , 1 ) ;
31-
32- this . zoom_target = new Vector ( 0 , 0 , 0 , 1 ) ;
33- this . zoom_speed = 0 ;
34- this . zoom_level = 1 ;
35-
36- this . desired_julia = 0 ;
37- this . current_julia = - 1 ;
38-
39- this . color_cycle = 0 ;
40-
41- this . extreme_mode = false ;
42-
43- this . drag_active = false ;
44- this . drag_point = new Vector ( 0 , 0 , 0 , 1 ) ;
45-
46- // Add resize listener
47- window . addEventListener ( 'resize' , ( ) => {
48- this . resize ( ) ;
49- } ) ;
50-
51- // Add keyboard event listener
52- window . addEventListener ( 'keypress' , ( event ) => {
53- switch ( event . key ) {
54- case 'z' :
55- this . desired_julia = ( this . desired_julia + 1 ) % 10 ;
56- event . preventDefault ( ) ;
57- break ;
58- case 'x' :
59- this . extreme_mode = ! this . extreme_mode ;
60- event . preventDefault ( ) ;
61- break ;
62- case 'c' :
63- this . zoom_target = this . mouse_position ;
64- if ( this . zoom_speed > 0 ) {
65- this . zoom_speed += 1 ;
66- } else {
67- this . zoom_speed = 1 ;
68- }
69- event . preventDefault ( ) ;
70- break ;
71- case 'v' :
72- this . zoom_target = this . mouse_position ;
73- if ( this . zoom_speed > 0 ) {
74- this . zoom_speed = - 1 ;
75- } else {
76- this . zoom_speed -= 1 ;
77- }
78- event . preventDefault ( ) ;
79- default :
80- break ;
81- }
82- } ) ;
83-
84- // Add click listeners
85- canvas . addEventListener ( 'mousedown' , ( event ) => {
86- this . drag_active = true ;
87-
88- this . drag_point = this . view_matrix . inverse ( ) . multiply_vector (
89- this . unproject (
90- event . layerX ,
91- this . canvas . clientHeight - event . layerY ,
92- 0
93- )
94- ) ;
95- } ) ;
96- canvas . addEventListener ( 'mouseup' , ( event ) => {
97- this . drag_active = false ;
98- } ) ;
99- canvas . addEventListener ( 'mousemove' , ( event ) => {
100- // Unproject mouse coords into scene coords.
101- this . mouse_position = this . view_matrix . inverse ( ) . multiply_vector (
102- this . unproject ( event . layerX , this . canvas . clientHeight - event . layerY , 0.5 )
103- ) ;
104-
105- // Only move if the mouse is down.
106- if ( ! this . drag_active ) {
107- return ;
108- }
109-
110- // Stop any zooming going on.
111- this . zoom_speed = 0 ;
112-
113- // Set the camera position to: current pos - mouse pos + initial click pos
114- this . set_camera_position (
115- this . camera_position . x - this . mouse_position . x + this . drag_point . x ,
116- this . camera_position . y - this . mouse_position . y + this . drag_point . y ,
117- this . camera_position . z
118- ) ;
119- } ) ;
120-
121- // Add mouse wheel listener
122- canvas . addEventListener ( 'wheel' , ( event ) => {
123- this . zoom_target = this . mouse_position ;
124- if ( event . deltaY > 0 ) {
125- if ( this . zoom_speed > 0 ) {
126- this . zoom_speed += 1 ;
127- } else {
128- this . zoom_speed = 1 ;
129- }
130- } else {
131- if ( this . zoom_speed > 0 ) {
132- this . zoom_speed = - 1 ;
133- } else {
134- this . zoom_speed -= 1 ;
135- }
136- }
137- } ) ;
13832 }
13933
14034 /**
@@ -144,6 +38,14 @@ export class GL {
14438 return this . gl ;
14539 }
14640
41+ /**
42+ * Add a callable hook to be run on each render pass.
43+ *
44+ * @param {callable } hook
45+ */
46+ add_render_hook ( hook ) {
47+ this . render_hooks . push ( hook ) ;
48+ }
14749
14850 /**
14951 * Create a vertex shader from the given source.
@@ -247,14 +149,31 @@ export class GL {
247149 * @param {float } z
248150 */
249151 set_camera_position ( x , y , z ) {
250- // Stay within the bounds of the quad.
251- if ( x < - 2 || x > 1 || y < - 1 || y > 1 ) {
252- return ;
253- }
254152 this . camera_position = new Vector ( x , y , z ) ;
255153 this . view_matrix = Matrix . identity ( ) . translate ( - x , - y , - z ) ;
256154 }
257155
156+ /**
157+ * Translates the position of the camera.
158+ *
159+ * @param {float } x
160+ * @param {float } y
161+ * @param {float } z
162+ */
163+ translate_camera_position ( x , y , z ) {
164+ this . camera_position = new Vector (
165+ this . camera_position . x + x ,
166+ this . camera_position . y + y ,
167+ this . camera_position . z + z ,
168+ 0
169+ ) ;
170+ this . view_matrix = Matrix . identity ( ) . translate (
171+ - this . camera_position . x ,
172+ - this . camera_position . y ,
173+ - this . camera_position . z
174+ ) ;
175+ }
176+
258177 /**
259178 * Computes world coordinates from given screen coordinates.
260179 *
@@ -352,125 +271,6 @@ export class GL {
352271
353272 this . objects . forEach ( ( object ) => object . render ( Matrix . identity ( ) ) ) ;
354273 }
355-
356- /**
357- * Perform zoom calculations.
358- *
359- * @param {integer } frame_delta
360- */
361- zoom ( frame_delta ) {
362- if ( this . zoom_speed === 0 ) {
363- return false ;
364- }
365-
366- // Find the vector from the current camera position to the zoom target.
367- // Scale by the frame_delta so that the movement would occur in 1 / zoom_speed seconds.
368- const movement_vector = new Vector (
369- this . zoom_target . x - this . camera_position . x ,
370- this . zoom_target . y - this . camera_position . y ,
371- this . zoom_target . z - this . camera_position . z ,
372- - this . camera_position . w ,
373- ) . multiply ( frame_delta * Math . abs ( this . zoom_speed ) / 1000 ) ;
374-
375- // Update the camera position along the movement vector.
376- this . set_camera_position (
377- this . camera_position . x + movement_vector . x ,
378- this . camera_position . y + movement_vector . y ,
379- this . camera_position . z + movement_vector . z ,
380- ) ;
381-
382- // Scale the projection matrix for the zoom effect.
383- if ( ( this . zoom_level < 30000 && this . zoom_speed < 0 )
384- || ( this . zoom_level > 1 && this . zoom_speed > 0 ) ) {
385- const scale_factor = 1 + ( frame_delta * - this . zoom_speed / 1000 ) ;
386- this . projection_matrix = this . projection_matrix . scale (
387- scale_factor ,
388- scale_factor ,
389- 1
390- ) ;
391-
392- this . zoom_level *= scale_factor ;
393- }
394-
395- // Reduce the zoom speed over time.
396- this . zoom_speed *= 1 - ( frame_delta / 1000 ) ;
397- if ( Math . abs ( this . zoom_speed ) < 0.005 ) {
398- this . zoom_speed = 0 ;
399- }
400-
401- return true ;
402- }
403-
404- /**
405- * Cycle the color rotation float.
406- *
407- * @param {integer } frame_delta
408- */
409- cycle ( frame_delta ) {
410- let speed = 200 ;
411- if ( this . extreme_mode ) {
412- speed = 10 ;
413- }
414- this . color_cycle = ( this . color_cycle + frame_delta / speed ) % 1024.0 ;
415-
416- this . get_shader_program ( ) . set_uniform_float (
417- 'continuous_cycle' ,
418- this . color_cycle
419- ) ;
420-
421- return true ;
422- }
423-
424- /**
425- * Switch the rendered set.
426- */
427- switch ( ) {
428- if ( this . current_julia === this . desired_julia ) {
429- return false ;
430- }
431-
432- this . current_julia = this . desired_julia ;
433-
434- let c ;
435- switch ( this . current_julia ) {
436- case 0 :
437- c = new Vector ( 0 , 0 , 0 , 0 ) ;
438- break ;
439- case 1 :
440- c = new Vector ( - 0.4 , 0.6 , 0 , 0 ) ;
441- break ;
442- case 2 :
443- c = new Vector ( 0.285 , 0 , 0 , 0 ) ;
444- break ;
445- case 3 :
446- c = new Vector ( 0.285 , 0.01 , 0 , 0 ) ;
447- break ;
448- case 4 :
449- c = new Vector ( 0.45 , 0.1428 , 0 , 0 ) ;
450- break ;
451- case 5 :
452- c = new Vector ( - 0.70176 , - 0.3842 , 0 , 0 ) ;
453- break ;
454- case 6 :
455- c = new Vector ( - 0.835 , - 0.2321 , 0 , 0 ) ;
456- break ;
457- case 7 :
458- c = new Vector ( - 0.8 , 0.156 , 0 , 0 ) ;
459- break ;
460- case 8 :
461- c = new Vector ( - 0.7269 , 0.1889 , 0 , 0 ) ;
462- break ;
463- case 9 :
464- default :
465- c = new Vector ( 0 , - 0.8 , 0 , 0 ) ;
466- break ;
467- }
468-
469- this . get_shader_program ( ) . set_uniform_vec2 ( 'julia_constant' , c ) ;
470-
471- return true ;
472- }
473-
474274 /**
475275 * The event loop executed for each tick.
476276 */
@@ -487,9 +287,10 @@ export class GL {
487287 let scene_dirty = false ;
488288
489289 scene_dirty |= this . resize ( ) ;
490- scene_dirty |= this . zoom ( frame_delta ) ;
491- scene_dirty |= this . cycle ( frame_delta ) ;
492- scene_dirty |= this . switch ( ) ;
290+
291+ this . render_hooks . forEach ( ( hook ) => {
292+ scene_dirty |= hook ( frame_delta ) ;
293+ } ) ;
493294
494295 if ( scene_dirty ) {
495296 this . render ( ) ;
0 commit comments